41#ifndef INCLUDE_NLOHMANN_JSON_HPP_
42#define INCLUDE_NLOHMANN_JSON_HPP_
47#include <initializer_list>
83#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
84 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
85 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
86 #warning "Already included a different version of the library!"
91#define NLOHMANN_JSON_VERSION_MAJOR 3
92#define NLOHMANN_JSON_VERSION_MINOR 11
93#define NLOHMANN_JSON_VERSION_PATCH 3
95#ifndef JSON_DIAGNOSTICS
96 #define JSON_DIAGNOSTICS 0
99#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
100 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
104 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
106 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
109#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
110 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
112 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
115#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
116 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
120#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
121#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
122 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
124#define NLOHMANN_JSON_ABI_TAGS \
125 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
126 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
127 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
130#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
131 _v ## major ## _ ## minor ## _ ## patch
132#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
133 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
135#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
136#define NLOHMANN_JSON_NAMESPACE_VERSION
138#define NLOHMANN_JSON_NAMESPACE_VERSION \
139 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
140 NLOHMANN_JSON_VERSION_MINOR, \
141 NLOHMANN_JSON_VERSION_PATCH)
145#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
146#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
147 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
149#ifndef NLOHMANN_JSON_NAMESPACE
150#define NLOHMANN_JSON_NAMESPACE \
151 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
152 NLOHMANN_JSON_ABI_TAGS, \
153 NLOHMANN_JSON_NAMESPACE_VERSION)
156#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
157#define NLOHMANN_JSON_NAMESPACE_BEGIN \
160 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
161 NLOHMANN_JSON_ABI_TAGS, \
162 NLOHMANN_JSON_NAMESPACE_VERSION) \
166#ifndef NLOHMANN_JSON_NAMESPACE_END
167#define NLOHMANN_JSON_NAMESPACE_END \
185#include <forward_list>
190#include <type_traits>
191#include <unordered_map>
254#include <type_traits>
270NLOHMANN_JSON_NAMESPACE_BEGIN
278template<
typename ...Ts>
using void_t =
typename make_void<Ts...>::type;
281NLOHMANN_JSON_NAMESPACE_END
284NLOHMANN_JSON_NAMESPACE_BEGIN
295 void operator=(
nonesuch const&) =
delete;
296 void operator=(
nonesuch&&) =
delete;
299template<
class Default,
301 template<
class...>
class Op,
305 using value_t = std::false_type;
306 using type = Default;
309template<
class Default,
template<
class...>
class Op,
class... Args>
310struct detector<Default, void_t<Op<Args...>>, Op, Args...>
312 using value_t = std::true_type;
313 using type = Op<Args...>;
316template<
template<
class...>
class Op,
class... Args>
319template<
template<
class...>
class Op,
class... Args>
322template<
template<
class...>
class Op,
class... Args>
325template<
class Default,
template<
class...>
class Op,
class... Args>
328template<
class Default,
template<
class...>
class Op,
class... Args>
329using detected_or_t =
typename detected_or<Default, Op, Args...>::type;
331template<
class Expected,
template<
class...>
class Op,
class... Args>
332using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
334template<
class To,
template<
class...>
class Op,
class... Args>
335using is_detected_convertible =
336 std::is_convertible<detected_t<Op, Args...>, To>;
339NLOHMANN_JSON_NAMESPACE_END
357#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
358#if defined(JSON_HEDLEY_VERSION)
359 #undef JSON_HEDLEY_VERSION
361#define JSON_HEDLEY_VERSION 15
363#if defined(JSON_HEDLEY_STRINGIFY_EX)
364 #undef JSON_HEDLEY_STRINGIFY_EX
366#define JSON_HEDLEY_STRINGIFY_EX(x) #x
368#if defined(JSON_HEDLEY_STRINGIFY)
369 #undef JSON_HEDLEY_STRINGIFY
371#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
373#if defined(JSON_HEDLEY_CONCAT_EX)
374 #undef JSON_HEDLEY_CONCAT_EX
376#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
378#if defined(JSON_HEDLEY_CONCAT)
379 #undef JSON_HEDLEY_CONCAT
381#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
383#if defined(JSON_HEDLEY_CONCAT3_EX)
384 #undef JSON_HEDLEY_CONCAT3_EX
386#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
388#if defined(JSON_HEDLEY_CONCAT3)
389 #undef JSON_HEDLEY_CONCAT3
391#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
393#if defined(JSON_HEDLEY_VERSION_ENCODE)
394 #undef JSON_HEDLEY_VERSION_ENCODE
396#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
398#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
399 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
401#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
403#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
404 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
406#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
408#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
409 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
411#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
413#if defined(JSON_HEDLEY_GNUC_VERSION)
414 #undef JSON_HEDLEY_GNUC_VERSION
416#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
417 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
418#elif defined(__GNUC__)
419 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
422#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
423 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
425#if defined(JSON_HEDLEY_GNUC_VERSION)
426 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
428 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
431#if defined(JSON_HEDLEY_MSVC_VERSION)
432 #undef JSON_HEDLEY_MSVC_VERSION
434#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
435 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
436#elif defined(_MSC_FULL_VER) && !defined(__ICL)
437 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
438#elif defined(_MSC_VER) && !defined(__ICL)
439 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
442#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
443 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
445#if !defined(JSON_HEDLEY_MSVC_VERSION)
446 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
447#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
448 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
449#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
450 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
452 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
455#if defined(JSON_HEDLEY_INTEL_VERSION)
456 #undef JSON_HEDLEY_INTEL_VERSION
458#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
459 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
460#elif defined(__INTEL_COMPILER) && !defined(__ICL)
461 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
464#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
465 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
467#if defined(JSON_HEDLEY_INTEL_VERSION)
468 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
470 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
473#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
474 #undef JSON_HEDLEY_INTEL_CL_VERSION
476#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
477 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
480#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
481 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
483#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
484 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
486 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
489#if defined(JSON_HEDLEY_PGI_VERSION)
490 #undef JSON_HEDLEY_PGI_VERSION
492#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
493 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
496#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
497 #undef JSON_HEDLEY_PGI_VERSION_CHECK
499#if defined(JSON_HEDLEY_PGI_VERSION)
500 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
502 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
505#if defined(JSON_HEDLEY_SUNPRO_VERSION)
506 #undef JSON_HEDLEY_SUNPRO_VERSION
508#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
509 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
510#elif defined(__SUNPRO_C)
511 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
512#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
513 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
514#elif defined(__SUNPRO_CC)
515 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
518#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
519 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
521#if defined(JSON_HEDLEY_SUNPRO_VERSION)
522 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
524 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
527#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
528 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
530#if defined(__EMSCRIPTEN__)
531 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
534#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
535 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
537#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
538 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
540 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
543#if defined(JSON_HEDLEY_ARM_VERSION)
544 #undef JSON_HEDLEY_ARM_VERSION
546#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
547 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
548#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
549 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
552#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
553 #undef JSON_HEDLEY_ARM_VERSION_CHECK
555#if defined(JSON_HEDLEY_ARM_VERSION)
556 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
558 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
561#if defined(JSON_HEDLEY_IBM_VERSION)
562 #undef JSON_HEDLEY_IBM_VERSION
564#if defined(__ibmxl__)
565 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
566#elif defined(__xlC__) && defined(__xlC_ver__)
567 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
568#elif defined(__xlC__)
569 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
572#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
573 #undef JSON_HEDLEY_IBM_VERSION_CHECK
575#if defined(JSON_HEDLEY_IBM_VERSION)
576 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
578 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
581#if defined(JSON_HEDLEY_TI_VERSION)
582 #undef JSON_HEDLEY_TI_VERSION
585 defined(__TI_COMPILER_VERSION__) && \
587 defined(__TMS470__) || defined(__TI_ARM__) || \
588 defined(__MSP430__) || \
589 defined(__TMS320C2000__) \
591#if (__TI_COMPILER_VERSION__ >= 16000000)
592 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
596#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
597 #undef JSON_HEDLEY_TI_VERSION_CHECK
599#if defined(JSON_HEDLEY_TI_VERSION)
600 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
602 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
605#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
606 #undef JSON_HEDLEY_TI_CL2000_VERSION
608#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
609 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
612#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
613 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
615#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
616 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
618 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
621#if defined(JSON_HEDLEY_TI_CL430_VERSION)
622 #undef JSON_HEDLEY_TI_CL430_VERSION
624#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
625 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
628#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
629 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
631#if defined(JSON_HEDLEY_TI_CL430_VERSION)
632 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
634 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
637#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
638 #undef JSON_HEDLEY_TI_ARMCL_VERSION
640#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
641 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
644#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
645 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
647#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
648 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
650 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
653#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
654 #undef JSON_HEDLEY_TI_CL6X_VERSION
656#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
657 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
660#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
661 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
663#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
664 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
666 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
669#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
670 #undef JSON_HEDLEY_TI_CL7X_VERSION
672#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
673 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
676#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
677 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
679#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
680 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
682 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
685#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
686 #undef JSON_HEDLEY_TI_CLPRU_VERSION
688#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
689 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
692#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
693 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
695#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
696 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
698 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
701#if defined(JSON_HEDLEY_CRAY_VERSION)
702 #undef JSON_HEDLEY_CRAY_VERSION
705 #if defined(_RELEASE_PATCHLEVEL)
706 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
708 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
712#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
713 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
715#if defined(JSON_HEDLEY_CRAY_VERSION)
716 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
718 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
721#if defined(JSON_HEDLEY_IAR_VERSION)
722 #undef JSON_HEDLEY_IAR_VERSION
724#if defined(__IAR_SYSTEMS_ICC__)
726 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
728 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
732#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
733 #undef JSON_HEDLEY_IAR_VERSION_CHECK
735#if defined(JSON_HEDLEY_IAR_VERSION)
736 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
738 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
741#if defined(JSON_HEDLEY_TINYC_VERSION)
742 #undef JSON_HEDLEY_TINYC_VERSION
744#if defined(__TINYC__)
745 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
748#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
749 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
751#if defined(JSON_HEDLEY_TINYC_VERSION)
752 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
754 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
757#if defined(JSON_HEDLEY_DMC_VERSION)
758 #undef JSON_HEDLEY_DMC_VERSION
761 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
764#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
765 #undef JSON_HEDLEY_DMC_VERSION_CHECK
767#if defined(JSON_HEDLEY_DMC_VERSION)
768 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
770 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
773#if defined(JSON_HEDLEY_COMPCERT_VERSION)
774 #undef JSON_HEDLEY_COMPCERT_VERSION
776#if defined(__COMPCERT_VERSION__)
777 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
780#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
781 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
783#if defined(JSON_HEDLEY_COMPCERT_VERSION)
784 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
786 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
789#if defined(JSON_HEDLEY_PELLES_VERSION)
790 #undef JSON_HEDLEY_PELLES_VERSION
793 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
796#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
797 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
799#if defined(JSON_HEDLEY_PELLES_VERSION)
800 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
802 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
805#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
806 #undef JSON_HEDLEY_MCST_LCC_VERSION
808#if defined(__LCC__) && defined(__LCC_MINOR__)
809 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
812#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
813 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
815#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
816 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
818 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
821#if defined(JSON_HEDLEY_GCC_VERSION)
822 #undef JSON_HEDLEY_GCC_VERSION
825 defined(JSON_HEDLEY_GNUC_VERSION) && \
826 !defined(__clang__) && \
827 !defined(JSON_HEDLEY_INTEL_VERSION) && \
828 !defined(JSON_HEDLEY_PGI_VERSION) && \
829 !defined(JSON_HEDLEY_ARM_VERSION) && \
830 !defined(JSON_HEDLEY_CRAY_VERSION) && \
831 !defined(JSON_HEDLEY_TI_VERSION) && \
832 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
833 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
834 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
835 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
836 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
837 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
838 !defined(__COMPCERT__) && \
839 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
840 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
843#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
844 #undef JSON_HEDLEY_GCC_VERSION_CHECK
846#if defined(JSON_HEDLEY_GCC_VERSION)
847 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
849 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
852#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
853 #undef JSON_HEDLEY_HAS_ATTRIBUTE
856 defined(__has_attribute) && \
858 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
860# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
862# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
865#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
866 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
868#if defined(__has_attribute)
869 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
871 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
874#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
875 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
877#if defined(__has_attribute)
878 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
880 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
883#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
884 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
887 defined(__has_cpp_attribute) && \
888 defined(__cplusplus) && \
889 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
890 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
892 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
895#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
896 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
898#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
899 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
901 !defined(JSON_HEDLEY_PGI_VERSION) && \
902 !defined(JSON_HEDLEY_IAR_VERSION) && \
903 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
904 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
905 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
907 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
910#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
911 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
913#if defined(__has_cpp_attribute) && defined(__cplusplus)
914 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
916 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
919#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
920 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
922#if defined(__has_cpp_attribute) && defined(__cplusplus)
923 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
925 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
928#if defined(JSON_HEDLEY_HAS_BUILTIN)
929 #undef JSON_HEDLEY_HAS_BUILTIN
931#if defined(__has_builtin)
932 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
934 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
937#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
938 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
940#if defined(__has_builtin)
941 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
943 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
946#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
947 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
949#if defined(__has_builtin)
950 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
952 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
955#if defined(JSON_HEDLEY_HAS_FEATURE)
956 #undef JSON_HEDLEY_HAS_FEATURE
958#if defined(__has_feature)
959 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
961 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
964#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
965 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
967#if defined(__has_feature)
968 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
970 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
973#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
974 #undef JSON_HEDLEY_GCC_HAS_FEATURE
976#if defined(__has_feature)
977 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
979 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
982#if defined(JSON_HEDLEY_HAS_EXTENSION)
983 #undef JSON_HEDLEY_HAS_EXTENSION
985#if defined(__has_extension)
986 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
988 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
991#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
992 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
994#if defined(__has_extension)
995 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
997 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1000#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
1001 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
1003#if defined(__has_extension)
1004 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
1006 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1009#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1010 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1012#if defined(__has_declspec_attribute)
1013 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1015 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1018#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1019 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1021#if defined(__has_declspec_attribute)
1022 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1024 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1027#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1028 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1030#if defined(__has_declspec_attribute)
1031 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1033 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1036#if defined(JSON_HEDLEY_HAS_WARNING)
1037 #undef JSON_HEDLEY_HAS_WARNING
1039#if defined(__has_warning)
1040 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1042 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1045#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1046 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1048#if defined(__has_warning)
1049 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1051 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1054#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1055 #undef JSON_HEDLEY_GCC_HAS_WARNING
1057#if defined(__has_warning)
1058 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1060 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1064 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1065 defined(__clang__) || \
1066 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1067 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1068 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1069 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1070 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1071 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1072 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1073 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1074 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1075 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1076 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1077 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1078 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1079 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1080 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1081 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1082 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1083#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1084 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1086 #define JSON_HEDLEY_PRAGMA(value)
1089#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1090 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1092#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1093 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1095#if defined(__clang__)
1096 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1097 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1098#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1099 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1100 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1101#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1102 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1103 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1105 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1106 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1107 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1108 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1109#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1113 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1114 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1115 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1116 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1117 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1118 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1119 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1120 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1121#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1122 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1123 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1125 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1126 #define JSON_HEDLEY_DIAGNOSTIC_POP
1131#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1132 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1134#if defined(__cplusplus)
1135# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1136# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1137# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1138# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1139 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1140 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1141 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1142 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1144 JSON_HEDLEY_DIAGNOSTIC_POP
1146# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1147 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1148 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1149 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1151 JSON_HEDLEY_DIAGNOSTIC_POP
1154# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1155 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1156 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1158 JSON_HEDLEY_DIAGNOSTIC_POP
1162#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1163 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1166#if defined(JSON_HEDLEY_CONST_CAST)
1167 #undef JSON_HEDLEY_CONST_CAST
1169#if defined(__cplusplus)
1170# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1172 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1173 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1174 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1175# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1176 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1177 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1179 JSON_HEDLEY_DIAGNOSTIC_POP \
1182# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1185#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1186 #undef JSON_HEDLEY_REINTERPRET_CAST
1188#if defined(__cplusplus)
1189 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1191 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1194#if defined(JSON_HEDLEY_STATIC_CAST)
1195 #undef JSON_HEDLEY_STATIC_CAST
1197#if defined(__cplusplus)
1198 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1200 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1203#if defined(JSON_HEDLEY_CPP_CAST)
1204 #undef JSON_HEDLEY_CPP_CAST
1206#if defined(__cplusplus)
1207# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1208# define JSON_HEDLEY_CPP_CAST(T, expr) \
1209 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1210 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1212 JSON_HEDLEY_DIAGNOSTIC_POP
1213# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1214# define JSON_HEDLEY_CPP_CAST(T, expr) \
1215 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1216 _Pragma("diag_suppress=Pe137") \
1217 JSON_HEDLEY_DIAGNOSTIC_POP
1219# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1222# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1225#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1226 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1228#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1229 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1230#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1231 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1232#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1233 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1234#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1235 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1236#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1237 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1238#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1239 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1240#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1241 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1242#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1243 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1245 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1246 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1247 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1248 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1249 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1250 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1251 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1252 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1253 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1254 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1255 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1256 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1257#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1258 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1259#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1260 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1261#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1262 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1263#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1269#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1270 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1272#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1273 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1274#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1275 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1276#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1277 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1278#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1279 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1280#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1282#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1285 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1286 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1287 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1288 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1289 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1290#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1291 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1292#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1293 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1294#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1300#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1301 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1303#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1305#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1307#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1308 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1309#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1310 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1311#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1312 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1313#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1314 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1315#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1316 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1317#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1318 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1320 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1321 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1322 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1323 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1324#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1325 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1326#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1327 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1329 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1332#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1333 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1335#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1336 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1337#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1338 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1339#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1340 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1342 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1345#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1346 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1348#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1349 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1350#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1351 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1352#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1353 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1354#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1355 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1357 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1360#if defined(JSON_HEDLEY_DEPRECATED)
1361 #undef JSON_HEDLEY_DEPRECATED
1363#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1364 #undef JSON_HEDLEY_DEPRECATED_FOR
1367 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1368 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1369 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1370 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1372 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1373 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1374 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1375 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1376 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1377 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1378 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1379 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1380 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1381 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1382 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1383 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1384 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1385 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1386#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1387 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1388 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1390 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1391 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1392 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1393 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1394 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1395 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1396 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1397 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1398 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1399 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1400 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1401 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1402 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1403 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1404 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1405 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1406 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1409 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1410 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1411 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1412 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1413 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1414#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1415 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1416 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1418 #define JSON_HEDLEY_DEPRECATED(since)
1419 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1422#if defined(JSON_HEDLEY_UNAVAILABLE)
1423 #undef JSON_HEDLEY_UNAVAILABLE
1426 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1427 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1428 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1429 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1430 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1432 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1435#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1436 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1438#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1439 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1442 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1443 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1444 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1445 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1446 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1447 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1448 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1449 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1450 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1451 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1452 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1453 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1454 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1455 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1456 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1457 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1458 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1461#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1462 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1463 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1464#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1465 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1466 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1467#elif defined(_Check_return_)
1468 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1469 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1471 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1472 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1475#if defined(JSON_HEDLEY_SENTINEL)
1476 #undef JSON_HEDLEY_SENTINEL
1479 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1480 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1481 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1482 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1483 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1484 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1486 #define JSON_HEDLEY_SENTINEL(position)
1489#if defined(JSON_HEDLEY_NO_RETURN)
1490 #undef JSON_HEDLEY_NO_RETURN
1492#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1493 #define JSON_HEDLEY_NO_RETURN __noreturn
1495 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1496 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1497 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1498#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1499 #define JSON_HEDLEY_NO_RETURN _Noreturn
1500#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1501 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1503 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1504 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1505 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1506 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1507 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1508 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1509 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1510 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1511 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1512 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1513 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1514 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1515 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1516 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1517 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1518 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1519 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1520 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1521#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1522 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1524 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1525 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1526 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1527#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1528 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1529#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1530 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1531#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1532 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1534 #define JSON_HEDLEY_NO_RETURN
1537#if defined(JSON_HEDLEY_NO_ESCAPE)
1538 #undef JSON_HEDLEY_NO_ESCAPE
1540#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1541 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1543 #define JSON_HEDLEY_NO_ESCAPE
1546#if defined(JSON_HEDLEY_UNREACHABLE)
1547 #undef JSON_HEDLEY_UNREACHABLE
1549#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1550 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1552#if defined(JSON_HEDLEY_ASSUME)
1553 #undef JSON_HEDLEY_ASSUME
1556 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1557 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1558 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1559 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1560#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1561 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1563 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1564 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1565 #if defined(__cplusplus)
1566 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1568 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1572 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1573 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1574 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1575 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1576 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1577 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1578 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1579 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1580#elif defined(JSON_HEDLEY_ASSUME)
1581 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1583#if !defined(JSON_HEDLEY_ASSUME)
1584 #if defined(JSON_HEDLEY_UNREACHABLE)
1585 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1587 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1590#if defined(JSON_HEDLEY_UNREACHABLE)
1592 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1593 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1594 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1596 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1599 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1601#if !defined(JSON_HEDLEY_UNREACHABLE)
1602 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1605JSON_HEDLEY_DIAGNOSTIC_PUSH
1606#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1607 #pragma clang diagnostic ignored "-Wpedantic"
1609#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1610 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1612#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1613 #if defined(__clang__)
1614 #pragma clang diagnostic ignored "-Wvariadic-macros"
1615 #elif defined(JSON_HEDLEY_GCC_VERSION)
1616 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1619#if defined(JSON_HEDLEY_NON_NULL)
1620 #undef JSON_HEDLEY_NON_NULL
1623 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1624 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1625 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1626 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1627 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1629 #define JSON_HEDLEY_NON_NULL(...)
1631JSON_HEDLEY_DIAGNOSTIC_POP
1633#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1634 #undef JSON_HEDLEY_PRINTF_FORMAT
1636#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1637 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1638#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1639 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1641 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1642 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1643 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1644 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1645 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1646 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1647 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1648 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1649 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1650 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1651 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1652 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1653 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1654 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1655 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1656 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1657 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1658 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1659#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1660 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1662 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1665#if defined(JSON_HEDLEY_CONSTEXPR)
1666 #undef JSON_HEDLEY_CONSTEXPR
1668#if defined(__cplusplus)
1669 #if __cplusplus >= 201103L
1670 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1673#if !defined(JSON_HEDLEY_CONSTEXPR)
1674 #define JSON_HEDLEY_CONSTEXPR
1677#if defined(JSON_HEDLEY_PREDICT)
1678 #undef JSON_HEDLEY_PREDICT
1680#if defined(JSON_HEDLEY_LIKELY)
1681 #undef JSON_HEDLEY_LIKELY
1683#if defined(JSON_HEDLEY_UNLIKELY)
1684 #undef JSON_HEDLEY_UNLIKELY
1686#if defined(JSON_HEDLEY_UNPREDICTABLE)
1687 #undef JSON_HEDLEY_UNPREDICTABLE
1689#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1690 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1693 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1694 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1695 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1696# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1697# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1698# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1699# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1700# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1702 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1703 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1704 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1705 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1706 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1707 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1708 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1709 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1710 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1711 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1712 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1713 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1714 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1715 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1716 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1717 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1718# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1719 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1720# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1722 double hedley_probability_ = (probability); \
1723 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1725# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1727 double hedley_probability_ = (probability); \
1728 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1730# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1731# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1733# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1734# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1735# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1736# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1737# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1739#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1740 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1743#if defined(JSON_HEDLEY_MALLOC)
1744 #undef JSON_HEDLEY_MALLOC
1747 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1748 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1749 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1750 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1751 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1752 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1753 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1754 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1755 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1756 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1757 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1758 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1759 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1760 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1761 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1762 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1763 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1764 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1765 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1766#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1767 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1769 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1770 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1771 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1773 #define JSON_HEDLEY_MALLOC
1776#if defined(JSON_HEDLEY_PURE)
1777 #undef JSON_HEDLEY_PURE
1780 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1781 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1782 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1783 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1784 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1785 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1786 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1787 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1788 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1789 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1790 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1791 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1792 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1793 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1794 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1795 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1796 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1797 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1798 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1799# define JSON_HEDLEY_PURE __attribute__((__pure__))
1800#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1801# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1802#elif defined(__cplusplus) && \
1804 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1805 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1806 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1808# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1810# define JSON_HEDLEY_PURE
1813#if defined(JSON_HEDLEY_CONST)
1814 #undef JSON_HEDLEY_CONST
1817 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1818 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1819 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1820 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1821 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1822 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1823 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1824 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1825 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1826 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1827 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1828 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1829 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1830 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1831 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1832 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1833 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1834 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1835 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1836 #define JSON_HEDLEY_CONST __attribute__((__const__))
1838 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1839 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1841 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1844#if defined(JSON_HEDLEY_RESTRICT)
1845 #undef JSON_HEDLEY_RESTRICT
1847#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1848 #define JSON_HEDLEY_RESTRICT restrict
1850 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1851 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1852 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1853 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1854 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1855 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1856 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1857 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1858 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1859 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1860 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1861 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1862 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1863 defined(__clang__) || \
1864 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1865 #define JSON_HEDLEY_RESTRICT __restrict
1866#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1867 #define JSON_HEDLEY_RESTRICT _Restrict
1869 #define JSON_HEDLEY_RESTRICT
1872#if defined(JSON_HEDLEY_INLINE)
1873 #undef JSON_HEDLEY_INLINE
1876 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1877 (defined(__cplusplus) && (__cplusplus >= 199711L))
1878 #define JSON_HEDLEY_INLINE inline
1880 defined(JSON_HEDLEY_GCC_VERSION) || \
1881 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1882 #define JSON_HEDLEY_INLINE __inline__
1884 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1885 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1886 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1887 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1888 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1889 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1890 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1891 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1892 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1893 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1894 #define JSON_HEDLEY_INLINE __inline
1896 #define JSON_HEDLEY_INLINE
1899#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1900 #undef JSON_HEDLEY_ALWAYS_INLINE
1903 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1904 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1905 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1906 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1907 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1908 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1909 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1910 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1911 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1912 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1913 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1914 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1915 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1916 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1917 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1918 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1919 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1920 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1921 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1922# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1924 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1925 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1926# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1927#elif defined(__cplusplus) && \
1929 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1930 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1931 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1932 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1933 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1934 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1936# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1937#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1938# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1940# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1943#if defined(JSON_HEDLEY_NEVER_INLINE)
1944 #undef JSON_HEDLEY_NEVER_INLINE
1947 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1948 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1949 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1950 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1951 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1952 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1953 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1954 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1955 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1956 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1957 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1958 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1959 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1960 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1961 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1962 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1963 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1964 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1965 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1966 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1968 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1969 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1970 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1971#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1972 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1973#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1974 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1975#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1976 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1977#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1978 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1979#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1980 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1982 #define JSON_HEDLEY_NEVER_INLINE
1985#if defined(JSON_HEDLEY_PRIVATE)
1986 #undef JSON_HEDLEY_PRIVATE
1988#if defined(JSON_HEDLEY_PUBLIC)
1989 #undef JSON_HEDLEY_PUBLIC
1991#if defined(JSON_HEDLEY_IMPORT)
1992 #undef JSON_HEDLEY_IMPORT
1994#if defined(_WIN32) || defined(__CYGWIN__)
1995# define JSON_HEDLEY_PRIVATE
1996# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1997# define JSON_HEDLEY_IMPORT __declspec(dllimport)
2000 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
2001 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2002 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
2003 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2004 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2005 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2007 defined(__TI_EABI__) && \
2009 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2010 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2013 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2014# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2015# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2017# define JSON_HEDLEY_PRIVATE
2018# define JSON_HEDLEY_PUBLIC
2020# define JSON_HEDLEY_IMPORT extern
2023#if defined(JSON_HEDLEY_NO_THROW)
2024 #undef JSON_HEDLEY_NO_THROW
2027 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2028 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2029 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2030 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2031 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2033 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2034 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2035 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2036 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2038 #define JSON_HEDLEY_NO_THROW
2041#if defined(JSON_HEDLEY_FALL_THROUGH)
2042 #undef JSON_HEDLEY_FALL_THROUGH
2045 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2046 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2047 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2048 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2049#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2050 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2051#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2052 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2053#elif defined(__fallthrough)
2054 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2056 #define JSON_HEDLEY_FALL_THROUGH
2059#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2060 #undef JSON_HEDLEY_RETURNS_NON_NULL
2063 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2064 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2065 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2066 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2067#elif defined(_Ret_notnull_)
2068 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2070 #define JSON_HEDLEY_RETURNS_NON_NULL
2073#if defined(JSON_HEDLEY_ARRAY_PARAM)
2074 #undef JSON_HEDLEY_ARRAY_PARAM
2077 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2078 !defined(__STDC_NO_VLA__) && \
2079 !defined(__cplusplus) && \
2080 !defined(JSON_HEDLEY_PGI_VERSION) && \
2081 !defined(JSON_HEDLEY_TINYC_VERSION)
2082 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2084 #define JSON_HEDLEY_ARRAY_PARAM(name)
2087#if defined(JSON_HEDLEY_IS_CONSTANT)
2088 #undef JSON_HEDLEY_IS_CONSTANT
2090#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2091 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2095#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2096 #undef JSON_HEDLEY_IS_CONSTEXPR_
2099 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2100 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2101 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2102 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2103 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2104 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2105 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2106 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2107 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2108 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2109 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2111#if !defined(__cplusplus)
2113 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2114 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2115 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2116 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2117 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2118 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2119 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2120#if defined(__INTPTR_TYPE__)
2121 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2124 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2128 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2129 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2130 !defined(JSON_HEDLEY_PGI_VERSION) && \
2131 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2132 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2133 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2134 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2135 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2136 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2137#if defined(__INTPTR_TYPE__)
2138 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2141 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2144 defined(JSON_HEDLEY_GCC_VERSION) || \
2145 defined(JSON_HEDLEY_INTEL_VERSION) || \
2146 defined(JSON_HEDLEY_TINYC_VERSION) || \
2147 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2148 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2149 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2150 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2151 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2152 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2154# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2158 ((void*) ((expr) * 0L) ) : \
2159((struct { char v[sizeof(void) * 2]; } *) 1) \
2165#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2166 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2167 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2169 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2171 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2172 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2174 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2177#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2178 #undef JSON_HEDLEY_BEGIN_C_DECLS
2180#if defined(JSON_HEDLEY_END_C_DECLS)
2181 #undef JSON_HEDLEY_END_C_DECLS
2183#if defined(JSON_HEDLEY_C_DECL)
2184 #undef JSON_HEDLEY_C_DECL
2186#if defined(__cplusplus)
2187 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2188 #define JSON_HEDLEY_END_C_DECLS }
2189 #define JSON_HEDLEY_C_DECL extern "C"
2191 #define JSON_HEDLEY_BEGIN_C_DECLS
2192 #define JSON_HEDLEY_END_C_DECLS
2193 #define JSON_HEDLEY_C_DECL
2196#if defined(JSON_HEDLEY_STATIC_ASSERT)
2197 #undef JSON_HEDLEY_STATIC_ASSERT
2200 !defined(__cplusplus) && ( \
2201 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2202 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2203 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2204 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2205 defined(_Static_assert) \
2207# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2209 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2210 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2211 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2212# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2214# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2217#if defined(JSON_HEDLEY_NULL)
2218 #undef JSON_HEDLEY_NULL
2220#if defined(__cplusplus)
2221 #if __cplusplus >= 201103L
2222 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2224 #define JSON_HEDLEY_NULL NULL
2226 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2229 #define JSON_HEDLEY_NULL NULL
2231 #define JSON_HEDLEY_NULL ((void*) 0)
2234#if defined(JSON_HEDLEY_MESSAGE)
2235 #undef JSON_HEDLEY_MESSAGE
2237#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2238# define JSON_HEDLEY_MESSAGE(msg) \
2239 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2240 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2241 JSON_HEDLEY_PRAGMA(message msg) \
2242 JSON_HEDLEY_DIAGNOSTIC_POP
2244 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2245 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2246# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2247#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2248# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2249#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2250# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2251#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2252# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2254# define JSON_HEDLEY_MESSAGE(msg)
2257#if defined(JSON_HEDLEY_WARNING)
2258 #undef JSON_HEDLEY_WARNING
2260#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2261# define JSON_HEDLEY_WARNING(msg) \
2262 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2263 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2264 JSON_HEDLEY_PRAGMA(clang warning msg) \
2265 JSON_HEDLEY_DIAGNOSTIC_POP
2267 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2268 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2269 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2270# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2272 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2273 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2274# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2276# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2279#if defined(JSON_HEDLEY_REQUIRE)
2280 #undef JSON_HEDLEY_REQUIRE
2282#if defined(JSON_HEDLEY_REQUIRE_MSG)
2283 #undef JSON_HEDLEY_REQUIRE_MSG
2285#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2286# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2287# define JSON_HEDLEY_REQUIRE(expr) \
2288 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2289 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2290 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2291 JSON_HEDLEY_DIAGNOSTIC_POP
2292# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2293 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2294 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2295 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2296 JSON_HEDLEY_DIAGNOSTIC_POP
2298# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2299# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2302# define JSON_HEDLEY_REQUIRE(expr)
2303# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2306#if defined(JSON_HEDLEY_FLAGS)
2307 #undef JSON_HEDLEY_FLAGS
2309#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2310 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2312 #define JSON_HEDLEY_FLAGS
2315#if defined(JSON_HEDLEY_FLAGS_CAST)
2316 #undef JSON_HEDLEY_FLAGS_CAST
2318#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2319# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2320 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2321 _Pragma("warning(disable:188)") \
2323 JSON_HEDLEY_DIAGNOSTIC_POP \
2326# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2329#if defined(JSON_HEDLEY_EMPTY_BASES)
2330 #undef JSON_HEDLEY_EMPTY_BASES
2333 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2334 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2335 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2337 #define JSON_HEDLEY_EMPTY_BASES
2342#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2343 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2345#if defined(__clang__)
2346 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2348 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2351#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2352 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2354#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2356#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2357 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2359#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2361#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2362 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2364#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2366#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2367 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2369#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2371#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2372 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2374#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2376#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2377 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2379#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2381#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2382 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2384#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2396#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2397 #if defined(__clang__)
2398 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2399 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2401 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2402 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2403 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2410#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2411 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2412 #define JSON_HAS_CPP_20
2413 #define JSON_HAS_CPP_17
2414 #define JSON_HAS_CPP_14
2415 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1)
2416 #define JSON_HAS_CPP_17
2417 #define JSON_HAS_CPP_14
2418 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2419 #define JSON_HAS_CPP_14
2422 #define JSON_HAS_CPP_11
2426 #if __has_include(<version>)
2431#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2432 #ifdef JSON_HAS_CPP_17
2433 #if defined(__cpp_lib_filesystem)
2434 #define JSON_HAS_FILESYSTEM 1
2435 #elif defined(__cpp_lib_experimental_filesystem)
2436 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2437 #elif !defined(__has_include)
2438 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2439 #elif __has_include(<filesystem>)
2440 #define JSON_HAS_FILESYSTEM 1
2441 #elif __has_include(<experimental/filesystem>)
2442 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2446 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2447 #undef JSON_HAS_FILESYSTEM
2448 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2452 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2453 #undef JSON_HAS_FILESYSTEM
2454 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2458 #if defined(__clang_major__) && __clang_major__ < 7
2459 #undef JSON_HAS_FILESYSTEM
2460 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2464 #if defined(_MSC_VER) && _MSC_VER < 1914
2465 #undef JSON_HAS_FILESYSTEM
2466 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2470 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2471 #undef JSON_HAS_FILESYSTEM
2472 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2476 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2477 #undef JSON_HAS_FILESYSTEM
2478 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2483#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2484 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2487#ifndef JSON_HAS_FILESYSTEM
2488 #define JSON_HAS_FILESYSTEM 0
2491#ifndef JSON_HAS_THREE_WAY_COMPARISON
2492 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2493 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2494 #define JSON_HAS_THREE_WAY_COMPARISON 1
2496 #define JSON_HAS_THREE_WAY_COMPARISON 0
2500#ifndef JSON_HAS_RANGES
2502 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2503 #define JSON_HAS_RANGES 0
2504 #elif defined(__cpp_lib_ranges)
2505 #define JSON_HAS_RANGES 1
2507 #define JSON_HAS_RANGES 0
2511#ifndef JSON_HAS_STATIC_RTTI
2512 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2513 #define JSON_HAS_STATIC_RTTI 1
2515 #define JSON_HAS_STATIC_RTTI 0
2519#ifdef JSON_HAS_CPP_17
2520 #define JSON_INLINE_VARIABLE inline
2522 #define JSON_INLINE_VARIABLE
2525#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2526 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2528 #define JSON_NO_UNIQUE_ADDRESS
2532#if defined(__clang__)
2533 #pragma clang diagnostic push
2534 #pragma clang diagnostic ignored "-Wdocumentation"
2535 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2539#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2540 #define JSON_THROW(exception) throw exception
2541 #define JSON_TRY try
2542 #define JSON_CATCH(exception) catch(exception)
2543 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2546 #define JSON_THROW(exception) std::abort()
2547 #define JSON_TRY if(true)
2548 #define JSON_CATCH(exception) if(false)
2549 #define JSON_INTERNAL_CATCH(exception) if(false)
2553#if defined(JSON_THROW_USER)
2555 #define JSON_THROW JSON_THROW_USER
2557#if defined(JSON_TRY_USER)
2559 #define JSON_TRY JSON_TRY_USER
2561#if defined(JSON_CATCH_USER)
2563 #define JSON_CATCH JSON_CATCH_USER
2564 #undef JSON_INTERNAL_CATCH
2565 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2567#if defined(JSON_INTERNAL_CATCH_USER)
2568 #undef JSON_INTERNAL_CATCH
2569 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2573#if !defined(JSON_ASSERT)
2575 #define JSON_ASSERT(x) assert(x)
2579#if defined(JSON_TESTS_PRIVATE)
2580 #define JSON_PRIVATE_UNLESS_TESTED public
2582 #define JSON_PRIVATE_UNLESS_TESTED private
2590#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2591 template<typename BasicJsonType> \
2592 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2594 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2595 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2596 auto it = std::find_if(std::begin(m), std::end(m), \
2597 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2599 return ej_pair.first == e; \
2601 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2603 template<typename BasicJsonType> \
2604 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2606 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2607 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2608 auto it = std::find_if(std::begin(m), std::end(m), \
2609 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2611 return ej_pair.second == j; \
2613 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2619#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2620 template<template<typename, typename, typename...> class ObjectType, \
2621 template<typename, typename...> class ArrayType, \
2622 class StringType, class BooleanType, class NumberIntegerType, \
2623 class NumberUnsignedType, class NumberFloatType, \
2624 template<typename> class AllocatorType, \
2625 template<typename, typename = void> class JSONSerializer, \
2627 class CustomBaseClass>
2629#define NLOHMANN_BASIC_JSON_TPL \
2630 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2631 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2632 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2636#define NLOHMANN_JSON_EXPAND( x ) x
2637#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2638#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2639 NLOHMANN_JSON_PASTE64, \
2640 NLOHMANN_JSON_PASTE63, \
2641 NLOHMANN_JSON_PASTE62, \
2642 NLOHMANN_JSON_PASTE61, \
2643 NLOHMANN_JSON_PASTE60, \
2644 NLOHMANN_JSON_PASTE59, \
2645 NLOHMANN_JSON_PASTE58, \
2646 NLOHMANN_JSON_PASTE57, \
2647 NLOHMANN_JSON_PASTE56, \
2648 NLOHMANN_JSON_PASTE55, \
2649 NLOHMANN_JSON_PASTE54, \
2650 NLOHMANN_JSON_PASTE53, \
2651 NLOHMANN_JSON_PASTE52, \
2652 NLOHMANN_JSON_PASTE51, \
2653 NLOHMANN_JSON_PASTE50, \
2654 NLOHMANN_JSON_PASTE49, \
2655 NLOHMANN_JSON_PASTE48, \
2656 NLOHMANN_JSON_PASTE47, \
2657 NLOHMANN_JSON_PASTE46, \
2658 NLOHMANN_JSON_PASTE45, \
2659 NLOHMANN_JSON_PASTE44, \
2660 NLOHMANN_JSON_PASTE43, \
2661 NLOHMANN_JSON_PASTE42, \
2662 NLOHMANN_JSON_PASTE41, \
2663 NLOHMANN_JSON_PASTE40, \
2664 NLOHMANN_JSON_PASTE39, \
2665 NLOHMANN_JSON_PASTE38, \
2666 NLOHMANN_JSON_PASTE37, \
2667 NLOHMANN_JSON_PASTE36, \
2668 NLOHMANN_JSON_PASTE35, \
2669 NLOHMANN_JSON_PASTE34, \
2670 NLOHMANN_JSON_PASTE33, \
2671 NLOHMANN_JSON_PASTE32, \
2672 NLOHMANN_JSON_PASTE31, \
2673 NLOHMANN_JSON_PASTE30, \
2674 NLOHMANN_JSON_PASTE29, \
2675 NLOHMANN_JSON_PASTE28, \
2676 NLOHMANN_JSON_PASTE27, \
2677 NLOHMANN_JSON_PASTE26, \
2678 NLOHMANN_JSON_PASTE25, \
2679 NLOHMANN_JSON_PASTE24, \
2680 NLOHMANN_JSON_PASTE23, \
2681 NLOHMANN_JSON_PASTE22, \
2682 NLOHMANN_JSON_PASTE21, \
2683 NLOHMANN_JSON_PASTE20, \
2684 NLOHMANN_JSON_PASTE19, \
2685 NLOHMANN_JSON_PASTE18, \
2686 NLOHMANN_JSON_PASTE17, \
2687 NLOHMANN_JSON_PASTE16, \
2688 NLOHMANN_JSON_PASTE15, \
2689 NLOHMANN_JSON_PASTE14, \
2690 NLOHMANN_JSON_PASTE13, \
2691 NLOHMANN_JSON_PASTE12, \
2692 NLOHMANN_JSON_PASTE11, \
2693 NLOHMANN_JSON_PASTE10, \
2694 NLOHMANN_JSON_PASTE9, \
2695 NLOHMANN_JSON_PASTE8, \
2696 NLOHMANN_JSON_PASTE7, \
2697 NLOHMANN_JSON_PASTE6, \
2698 NLOHMANN_JSON_PASTE5, \
2699 NLOHMANN_JSON_PASTE4, \
2700 NLOHMANN_JSON_PASTE3, \
2701 NLOHMANN_JSON_PASTE2, \
2702 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2703#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2704#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2705#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2706#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2707#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2708#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2709#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2710#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2711#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2712#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2713#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2714#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2715#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2716#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2717#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2718#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2719#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2720#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2721#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2722#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2723#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2724#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2725#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2726#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2727#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2728#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2729#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2730#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2731#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2732#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2733#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2734#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2735#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2736#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2737#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2738#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2739#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2740#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2741#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2742#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2743#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2744#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2745#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2746#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2747#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2748#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2749#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2750#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2751#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2752#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2753#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2754#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2755#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2756#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2757#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2758#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2759#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2760#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2761#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2762#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2763#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2764#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2765#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2767#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2768#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2769#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2776#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2777 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2778 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2780#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2781 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2782 friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2784#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2785 friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2792#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2793 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2794 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2796#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2797 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2799#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2800 inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2801 inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2809#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2810 namespace detail { \
2811 using std::std_name; \
2813 template<typename... T> \
2814 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2817 namespace detail2 { \
2818 struct std_name##_tag \
2822 template<typename... T> \
2823 std_name##_tag std_name(T&&...); \
2825 template<typename... T> \
2826 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2828 template<typename... T> \
2829 struct would_call_std_##std_name \
2831 static constexpr auto const value = ::nlohmann::detail:: \
2832 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2836 template<typename... T> \
2837 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2841#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2842 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2845#if JSON_USE_IMPLICIT_CONVERSIONS
2846 #define JSON_EXPLICIT
2848 #define JSON_EXPLICIT explicit
2851#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2852 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2855#ifndef JSON_USE_GLOBAL_UDLS
2856 #define JSON_USE_GLOBAL_UDLS 1
2859#if JSON_HAS_THREE_WAY_COMPARISON
2863NLOHMANN_JSON_NAMESPACE_BEGIN
2922#if JSON_HAS_THREE_WAY_COMPARISON
2923 inline std::partial_ordering operator<=>(
const value_t lhs,
const value_t rhs)
noexcept
2928 static constexpr std::array<std::uint8_t, 9> order = {{
2935 const auto l_index =
static_cast<std::size_t
>(lhs);
2936 const auto r_index =
static_cast<std::size_t
>(rhs);
2937#if JSON_HAS_THREE_WAY_COMPARISON
2938 if (l_index < order.size() && r_index < order.size())
2940 return order[l_index] <=> order[r_index];
2942 return std::partial_ordering::unordered;
2944 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2952#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2955 return std::is_lt(lhs <=> rhs);
2960NLOHMANN_JSON_NAMESPACE_END
2976NLOHMANN_JSON_NAMESPACE_BEGIN
2993template<
typename StringType>
2995 const StringType& t)
2997 JSON_ASSERT(!f.empty());
2998 for (
auto pos = s.find(f);
2999 pos != StringType::npos;
3000 s.replace(pos, f.size(), t),
3001 pos = s.find(f, pos + t.size()))
3012template<
typename StringType>
3027template<
typename StringType>
3035NLOHMANN_JSON_NAMESPACE_END
3053NLOHMANN_JSON_NAMESPACE_BEGIN
3068 constexpr operator size_t()
const
3075NLOHMANN_JSON_NAMESPACE_END
3093#include <type_traits>
3099NLOHMANN_JSON_NAMESPACE_BEGIN
3104using uncvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3106#ifdef JSON_HAS_CPP_14
3109using std::enable_if_t;
3110using std::index_sequence;
3111using std::make_index_sequence;
3112using std::index_sequence_for;
3117template<
bool B,
typename T =
void>
3118using enable_if_t =
typename std::enable_if<B, T>::type;
3144template <
typename T, T... Ints>
3147 using value_type = T;
3148 static constexpr std::size_t size()
noexcept
3150 return sizeof...(Ints);
3159template <
size_t... Ints>
3162namespace utility_internal
3165template <
typename Seq,
size_t SeqSize,
size_t Rem>
3169template <
typename T, T... Ints,
size_t SeqSize>
3175template <
typename T, T... Ints,
size_t SeqSize>
3178 using type =
integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3183template <
typename T,
size_t N>
3187 typename Extend <
typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3190template <
typename T>
3205template <
typename T, T N>
3206using make_integer_sequence =
typename utility_internal::Gen<T, N>::type;
3214using make_index_sequence = make_integer_sequence<size_t, N>;
3221template <
typename... Ts>
3222using index_sequence_for = make_index_sequence<
sizeof...(Ts)>;
3236 static JSON_INLINE_VARIABLE
constexpr T value{};
3239#ifndef JSON_HAS_CPP_17
3240 template<
typename T>
3244template<
typename T,
typename... Args>
3245inline constexpr std::array<T,
sizeof...(Args)> make_array(Args&& ... args)
3247 return std::array<T,
sizeof...(Args)> {{
static_cast<T
>(std::forward<Args>(args))...}};
3251NLOHMANN_JSON_NAMESPACE_END
3265#include <type_traits>
3290NLOHMANN_JSON_NAMESPACE_BEGIN
3294template<
typename It,
typename =
void>
3297template<
typename It>
3300 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3301 typename It::reference, typename It::iterator_category >>
3303 using difference_type =
typename It::difference_type;
3304 using value_type =
typename It::value_type;
3305 using pointer =
typename It::pointer;
3306 using reference =
typename It::reference;
3307 using iterator_category =
typename It::iterator_category;
3312template<
typename T,
typename =
void>
3326 using iterator_category = std::random_access_iterator_tag;
3327 using value_type = T;
3328 using difference_type = ptrdiff_t;
3330 using reference = T&;
3334NLOHMANN_JSON_NAMESPACE_END
3352NLOHMANN_JSON_NAMESPACE_BEGIN
3354NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3356NLOHMANN_JSON_NAMESPACE_END
3372NLOHMANN_JSON_NAMESPACE_BEGIN
3374NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3376NLOHMANN_JSON_NAMESPACE_END
3391#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3392 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3408 NLOHMANN_JSON_NAMESPACE_BEGIN
3417 template<
typename T =
void,
typename SFINAE =
void>
3422 template<
template<
typename U,
typename V,
typename... Args>
class ObjectType =
3424 template<
typename U,
typename... Args>
class ArrayType = std::vector,
3425 class StringType = std::string,
class BooleanType = bool,
3426 class NumberIntegerType = std::int64_t,
3427 class NumberUnsignedType = std::uint64_t,
3428 class NumberFloatType = double,
3429 template<
typename U>
class AllocatorType = std::allocator,
3430 template<
typename T,
typename SFINAE =
void>
class JSONSerializer =
3432 class BinaryType = std::vector<std::uint8_t>,
3433 class CustomBaseClass =
void>
3438 template<
typename RefStringType>
3449 template<
class Key,
class T,
class IgnoredLess,
class Allocator>
3456 NLOHMANN_JSON_NAMESPACE_END
3461NLOHMANN_JSON_NAMESPACE_BEGIN
3488NLOHMANN_BASIC_JSON_TPL_DECLARATION
3494template<
typename BasicJsonContext>
3496 std::integral_constant < bool,
3497 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3498 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3519using mapped_type_t =
typename T::mapped_type;
3522using key_type_t =
typename T::key_type;
3525using value_type_t =
typename T::value_type;
3528using difference_type_t =
typename T::difference_type;
3531using pointer_t =
typename T::pointer;
3534using reference_t =
typename T::reference;
3537using iterator_category_t =
typename T::iterator_category;
3539template<
typename T,
typename... Args>
3540using to_json_function =
decltype(T::to_json(std::declval<Args>()...));
3542template<
typename T,
typename... Args>
3543using from_json_function =
decltype(T::from_json(std::declval<Args>()...));
3545template<
typename T,
typename U>
3546using get_template_function =
decltype(std::declval<T>().template get<U>());
3549template<
typename BasicJsonType,
typename T,
typename =
void>
3556template <
typename BasicJsonType,
typename T>
3559 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3562template<
typename BasicJsonType,
typename T>
3565 using serializer =
typename BasicJsonType::template json_serializer<T, void>;
3567 static constexpr bool value =
3568 is_detected_exact<void, from_json_function, serializer,
3569 const BasicJsonType&, T&>
::value;
3574template<
typename BasicJsonType,
typename T,
typename =
void>
3577template<
typename BasicJsonType,
typename T>
3580 using serializer =
typename BasicJsonType::template json_serializer<T, void>;
3582 static constexpr bool value =
3583 is_detected_exact<T, from_json_function, serializer,
3589template<
typename BasicJsonType,
typename T,
typename =
void>
3592template<
typename BasicJsonType,
typename T>
3595 using serializer =
typename BasicJsonType::template json_serializer<T, void>;
3597 static constexpr bool value =
3598 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3603using detect_key_compare =
typename T::key_compare;
3606struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3609template<
typename BasicJsonType>
3612 using object_t =
typename BasicJsonType::object_t;
3613 using object_comparator_t =
typename BasicJsonType::default_object_comparator_t;
3614 using type =
typename std::conditional < has_key_compare<object_t>::value,
3615 typename object_t::key_compare, object_comparator_t>::type;
3618template<
typename BasicJsonType>
3619using actual_object_comparator_t =
typename actual_object_comparator<BasicJsonType>::type;
3634 using char_type =
unsigned char;
3635 using int_type = uint64_t;
3638 static int_type to_int_type(char_type c)
noexcept
3640 return static_cast<int_type
>(c);
3643 static char_type to_char_type(int_type i)
noexcept
3645 return static_cast<char_type
>(i);
3648 static constexpr int_type eof()
noexcept
3650 return static_cast<int_type
>(EOF);
3658 using char_type =
signed char;
3659 using int_type = uint64_t;
3662 static int_type to_int_type(char_type c)
noexcept
3664 return static_cast<int_type
>(c);
3667 static char_type to_char_type(int_type i)
noexcept
3669 return static_cast<char_type
>(i);
3672 static constexpr int_type eof()
noexcept
3674 return static_cast<int_type
>(EOF);
3685template<
class B,
class... Bn>
3687: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3690template<
class B>
struct negation : std::integral_constant < bool, !B::value > { };
3695template <
typename T>
3698template <
typename T1,
typename T2>
3700 :
conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3702template <
typename T1,
typename T2>
3704 :
conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3706template <
typename... Ts>
3708 :
conjunction<is_default_constructible<Ts>...> {};
3710template <
typename... Ts>
3712 :
conjunction<is_default_constructible<Ts>...> {};
3714template <
typename T,
typename... Args>
3717template <
typename T1,
typename T2>
3720template <
typename T1,
typename T2>
3723template <
typename... Ts>
3726template <
typename... Ts>
3729template<
typename T,
typename =
void>
3739 static constexpr auto value =
3740 is_detected<value_type_t, traits>::value &&
3741 is_detected<difference_type_t, traits>::value &&
3742 is_detected<pointer_t, traits>::value &&
3743 is_detected<iterator_category_t, traits>::value &&
3744 is_detected<reference_t, traits>::value;
3751 using t_ref =
typename std::add_lvalue_reference<T>::type;
3753 using iterator = detected_t<result_of_begin, t_ref>;
3754 using sentinel = detected_t<result_of_end, t_ref>;
3759 static constexpr auto is_iterator_begin =
3763 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3767using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3770using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3776template<
typename T,
typename =
void>
3782template<
typename BasicJsonType,
typename CompatibleObjectType,
3786template<
typename BasicJsonType,
typename CompatibleObjectType>
3788 BasicJsonType, CompatibleObjectType,
3789 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::
value&&
3790 is_detected<key_type_t, CompatibleObjectType>
::value >>
3792 using object_t =
typename BasicJsonType::object_t;
3795 static constexpr bool value =
3797 typename CompatibleObjectType::key_type>
::value &&
3799 typename CompatibleObjectType::mapped_type>
::value;
3802template<
typename BasicJsonType,
typename CompatibleObjectType>
3806template<
typename BasicJsonType,
typename ConstructibleObjectType,
3810template<
typename BasicJsonType,
typename ConstructibleObjectType>
3812 BasicJsonType, ConstructibleObjectType,
3813 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::
value&&
3814 is_detected<key_type_t, ConstructibleObjectType>
::value >>
3816 using object_t =
typename BasicJsonType::object_t;
3818 static constexpr bool value =
3820 (std::is_move_assignable<ConstructibleObjectType>::value ||
3821 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3823 typename object_t::key_type>
::value &&
3825 typename object_t::mapped_type,
3826 typename ConstructibleObjectType::mapped_type >
::value)) ||
3828 typename ConstructibleObjectType::mapped_type>
::value ||
3831 typename ConstructibleObjectType::mapped_type >
::value);
3834template<
typename BasicJsonType,
typename ConstructibleObjectType>
3837 ConstructibleObjectType> {};
3839template<
typename BasicJsonType,
typename CompatibleStringType>
3842 static constexpr auto value =
3846template<
typename BasicJsonType,
typename ConstructibleStringType>
3850#ifdef __INTEL_COMPILER
3851 using laundered_type =
decltype(std::declval<ConstructibleStringType>());
3853 using laundered_type = ConstructibleStringType;
3856 static constexpr auto value =
3859 is_detected_exact<
typename BasicJsonType::string_t::value_type,
3860 value_type_t, laundered_type >>::value;
3863template<
typename BasicJsonType,
typename CompatibleArrayType,
typename =
void>
3866template<
typename BasicJsonType,
typename CompatibleArrayType>
3868 BasicJsonType, CompatibleArrayType,
3870 is_detected<iterator_t, CompatibleArrayType>::
value&&
3874 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>
::value >>
3876 static constexpr bool value =
3878 range_value_t<CompatibleArrayType>>
::value;
3881template<
typename BasicJsonType,
typename CompatibleArrayType>
3885template<
typename BasicJsonType,
typename ConstructibleArrayType,
typename =
void>
3888template<
typename BasicJsonType,
typename ConstructibleArrayType>
3890 BasicJsonType, ConstructibleArrayType,
3891 enable_if_t<std::is_same<ConstructibleArrayType,
3892 typename BasicJsonType::value_type>
::value >>
3893 : std::true_type {};
3895template<
typename BasicJsonType,
typename ConstructibleArrayType>
3897 BasicJsonType, ConstructibleArrayType,
3898 enable_if_t < !std::is_same<ConstructibleArrayType,
3899 typename BasicJsonType::value_type>
::value&&
3902(std::is_move_assignable<ConstructibleArrayType>::value ||
3903 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3904is_detected<iterator_t, ConstructibleArrayType>
::value&&
3906is_detected<range_value_t, ConstructibleArrayType>
::value&&
3909!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>
::value&&
3911 detected_t<range_value_t, ConstructibleArrayType >>
::value >>
3913 using value_type = range_value_t<ConstructibleArrayType>;
3915 static constexpr bool value =
3916 std::is_same<value_type,
3917 typename BasicJsonType::array_t::value_type>
::value ||
3925template<
typename BasicJsonType,
typename ConstructibleArrayType>
3929template<
typename RealIntegerType,
typename CompatibleNumberIntegerType,
3933template<
typename RealIntegerType,
typename CompatibleNumberIntegerType>
3935 RealIntegerType, CompatibleNumberIntegerType,
3936 enable_if_t < std::is_integral<RealIntegerType>
::value&&
3937 std::is_integral<CompatibleNumberIntegerType>
::value&&
3938 !std::is_same<bool, CompatibleNumberIntegerType>
::value >>
3941 using RealLimits = std::numeric_limits<RealIntegerType>;
3942 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3944 static constexpr auto value =
3946 CompatibleNumberIntegerType>
::value &&
3947 CompatibleLimits::is_integer &&
3948 RealLimits::is_signed == CompatibleLimits::is_signed;
3951template<
typename RealIntegerType,
typename CompatibleNumberIntegerType>
3954 CompatibleNumberIntegerType> {};
3956template<
typename BasicJsonType,
typename CompatibleType,
typename =
void>
3959template<
typename BasicJsonType,
typename CompatibleType>
3961 BasicJsonType, CompatibleType,
3964 static constexpr bool value =
3968template<
typename BasicJsonType,
typename CompatibleType>
3972template<
typename T1,
typename T2>
3975template<
typename T1,
typename... Args>
3978template<
typename BasicJsonType,
typename T>
3981template<
typename BasicJsonType>
3984template<
typename BasicJsonType>
3989template<
template <
typename...>
class Primary,
typename T>
3992template<
template <
typename...>
class Primary,
typename... Args>
3999template<
typename Compare,
typename A,
typename B,
typename =
void>
4002template<
typename Compare,
typename A,
typename B>
4004decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4005decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4006>> : std::true_type {};
4009using detect_is_transparent =
typename T::is_transparent;
4013template<
typename Comparator,
typename ObjectKeyType,
typename KeyTypeCVRef,
bool RequireTransparentComparator =
true,
4014 bool ExcludeObjectKeyType = RequireTransparentComparator,
typename KeyType = uncvref_t<KeyTypeCVRef>>
4015using is_usable_as_key_type =
typename std::conditional <
4017 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4019 && (!RequireTransparentComparator
4020 || is_detected <detect_is_transparent, Comparator>::value)
4021 && !is_json_pointer<KeyType>::value,
4023 std::false_type >::type;
4031template<
typename BasicJsonType,
typename KeyTypeCVRef,
bool RequireTransparentComparator =
true,
4032 bool ExcludeObjectKeyType = RequireTransparentComparator,
typename KeyType = uncvref_t<KeyTypeCVRef>>
4033using is_usable_as_basic_json_key_type =
typename std::conditional <
4034 is_usable_as_key_type<
typename BasicJsonType::object_comparator_t,
4035 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4036 RequireTransparentComparator, ExcludeObjectKeyType>
::value
4039 std::false_type >::type;
4041template<
typename ObjectType,
typename KeyType>
4042using detect_erase_with_key_type =
decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4045template<
typename BasicJsonType,
typename KeyType>
4046using has_erase_with_key_type =
typename std::conditional <
4048 detect_erase_with_key_type,
4049 typename BasicJsonType::object_t, KeyType >
::value,
4051 std::false_type >::type;
4055template <
typename T>
4065 template <
typename C>
static one test(
decltype(&C::capacity) ) ;
4066 template <
typename C>
static two test(...);
4068 enum { value =
sizeof(test<T>(
nullptr)) ==
sizeof(
char) };
4072template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value,
int > = 0 >
4073T conditional_static_cast(U
value)
4075 return static_cast<T
>(
value);
4078template<typename T, typename U, enable_if_t<std::is_same<T, U>::value,
int> = 0>
4079T conditional_static_cast(U
value)
4084template<
typename... Types>
4085using all_integral = conjunction<std::is_integral<Types>...>;
4087template<
typename... Types>
4088using all_signed = conjunction<std::is_signed<Types>...>;
4090template<
typename... Types>
4091using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4094template<
typename... Types>
4095using same_sign = std::integral_constant < bool,
4098template<
typename OfType,
typename T>
4099using never_out_of_range = std::integral_constant < bool,
4100 (std::is_signed<OfType>::value && (
sizeof(T) <
sizeof(OfType)))
4101 || (same_sign<OfType, T>::value &&
sizeof(OfType) ==
sizeof(T)) >;
4103template<
typename OfType,
typename T,
4104 bool OfTypeSigned = std::is_signed<OfType>::value,
4105 bool TSigned = std::is_signed<T>::value>
4108template<
typename OfType,
typename T>
4111 static constexpr bool test(T val)
4113 using CommonType =
typename std::common_type<OfType, T>::type;
4114 return static_cast<CommonType
>(val) <=
static_cast<CommonType
>((std::numeric_limits<OfType>::max)());
4118template<
typename OfType,
typename T>
4121 static constexpr bool test(T val)
4123 using CommonType =
typename std::common_type<OfType, T>::type;
4124 return static_cast<CommonType
>(val) <=
static_cast<CommonType
>((std::numeric_limits<OfType>::max)());
4128template<
typename OfType,
typename T>
4131 static constexpr bool test(T val)
4133 using CommonType =
typename std::common_type<OfType, T>::type;
4134 return val >= 0 &&
static_cast<CommonType
>(val) <=
static_cast<CommonType
>((std::numeric_limits<OfType>::max)());
4138template<
typename OfType,
typename T>
4141 static constexpr bool test(T val)
4143 using CommonType =
typename std::common_type<OfType, T>::type;
4144 return static_cast<CommonType
>(val) >=
static_cast<CommonType
>((std::numeric_limits<OfType>::min)())
4145 &&
static_cast<CommonType
>(val) <=
static_cast<CommonType
>((std::numeric_limits<OfType>::max)());
4149template<
typename OfType,
typename T,
4150 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4151 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4154template<
typename OfType,
typename T>
4157 static constexpr bool test(T val)
4163template<
typename OfType,
typename T>
4166 static constexpr bool test(T )
4172template<
typename OfType,
typename T>
4173inline constexpr bool value_in_range_of(T val)
4179using bool_constant = std::integral_constant<bool, Value>;
4189inline constexpr bool is_c_string()
4191 using TUnExt =
typename std::remove_extent<T>::type;
4192 using TUnCVExt =
typename std::remove_cv<TUnExt>::type;
4193 using TUnPtr =
typename std::remove_pointer<T>::type;
4194 using TUnCVPtr =
typename std::remove_cv<TUnPtr>::type;
4196 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4197 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4219 return is_detected<detect_is_transparent, T>::value;
4231NLOHMANN_JSON_NAMESPACE_END
4253NLOHMANN_JSON_NAMESPACE_BEGIN
4257inline std::size_t concat_length()
4262template<
typename... Args>
4263inline std::size_t concat_length(
const char* cstr,
const Args& ... rest);
4265template<
typename StringType,
typename... Args>
4266inline std::size_t concat_length(
const StringType& str,
const Args& ... rest);
4268template<
typename... Args>
4269inline std::size_t concat_length(
const char ,
const Args& ... rest)
4271 return 1 + concat_length(rest...);
4274template<
typename... Args>
4275inline std::size_t concat_length(
const char* cstr,
const Args& ... rest)
4278 return ::strlen(cstr) + concat_length(rest...);
4281template<
typename StringType,
typename... Args>
4282inline std::size_t concat_length(
const StringType& str,
const Args& ... rest)
4284 return str.size() + concat_length(rest...);
4287template<
typename OutStringType>
4288inline void concat_into(OutStringType& )
4291template<
typename StringType,
typename Arg>
4292using string_can_append =
decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4294template<
typename StringType,
typename Arg>
4295using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4297template<
typename StringType,
typename Arg>
4298using string_can_append_op =
decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4300template<
typename StringType,
typename Arg>
4301using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4303template<
typename StringType,
typename Arg>
4304using string_can_append_iter =
decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4306template<
typename StringType,
typename Arg>
4307using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4309template<
typename StringType,
typename Arg>
4310using string_can_append_data =
decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4312template<
typename StringType,
typename Arg>
4313using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4315template <
typename OutStringType,
typename Arg,
typename... Args,
4316 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4317 && detect_string_can_append_op<OutStringType, Arg>::value,
int > = 0 >
4318inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4320template <
typename OutStringType,
typename Arg,
typename... Args,
4321 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4322 && !detect_string_can_append_op<OutStringType, Arg>::value
4323 && detect_string_can_append_iter<OutStringType, Arg>::value,
int > = 0 >
4324inline void concat_into(OutStringType& out,
const Arg& arg, Args && ... rest);
4326template <
typename OutStringType,
typename Arg,
typename... Args,
4327 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4328 && !detect_string_can_append_op<OutStringType, Arg>::value
4329 && !detect_string_can_append_iter<OutStringType, Arg>::value
4330 && detect_string_can_append_data<OutStringType, Arg>::value,
int > = 0 >
4331inline void concat_into(OutStringType& out,
const Arg& arg, Args && ... rest);
4333template<
typename OutStringType,
typename Arg,
typename... Args,
4334 enable_if_t<detect_string_can_append<OutStringType, Arg>::value,
int> = 0>
4335inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4337 out.append(std::forward<Arg>(arg));
4338 concat_into(out, std::forward<Args>(rest)...);
4341template <
typename OutStringType,
typename Arg,
typename... Args,
4342 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4343 && detect_string_can_append_op<OutStringType, Arg>::value,
int > >
4344inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4346 out += std::forward<Arg>(arg);
4347 concat_into(out, std::forward<Args>(rest)...);
4350template <
typename OutStringType,
typename Arg,
typename... Args,
4351 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4352 && !detect_string_can_append_op<OutStringType, Arg>::value
4353 && detect_string_can_append_iter<OutStringType, Arg>::value,
int > >
4354inline void concat_into(OutStringType& out,
const Arg& arg, Args&& ... rest)
4356 out.append(arg.begin(), arg.end());
4357 concat_into(out, std::forward<Args>(rest)...);
4360template <
typename OutStringType,
typename Arg,
typename... Args,
4361 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4362 && !detect_string_can_append_op<OutStringType, Arg>::value
4363 && !detect_string_can_append_iter<OutStringType, Arg>::value
4364 && detect_string_can_append_data<OutStringType, Arg>::value,
int > >
4365inline void concat_into(OutStringType& out,
const Arg& arg, Args&& ... rest)
4367 out.append(arg.data(), arg.size());
4368 concat_into(out, std::forward<Args>(rest)...);
4371template<
typename OutStringType = std::string,
typename... Args>
4372inline OutStringType concat(Args && ... args)
4375 str.reserve(concat_length(args...));
4376 concat_into(str, std::forward<Args>(args)...);
4381NLOHMANN_JSON_NAMESPACE_END
4384NLOHMANN_JSON_NAMESPACE_BEGIN
4398 const char*
what() const noexcept
override
4407 JSON_HEDLEY_NON_NULL(3)
4408 exception(
int id_, const
char* what_arg) :
id(id_),
m(what_arg) {}
4410 static std::string name(
const std::string& ename,
int id_)
4412 return concat(
"[json.exception.", ename,
'.', std::to_string(id_),
"] ");
4415 static std::string diagnostics(std::nullptr_t )
4420 template<
typename BasicJsonType>
4421 static std::string diagnostics(
const BasicJsonType* leaf_element)
4424 std::vector<std::string> tokens;
4425 for (
const auto* current = leaf_element; current !=
nullptr && current->m_parent !=
nullptr; current = current->m_parent)
4427 switch (current->m_parent->type())
4431 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4433 if (¤t->m_parent->m_data.m_value.array->operator[](i) == current)
4435 tokens.emplace_back(std::to_string(i));
4444 for (
const auto& element : *current->m_parent->m_data.m_value.
object)
4446 if (&element.second == current)
4448 tokens.emplace_back(element.first.c_str());
4473 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4474 [](
const std::string & a,
const std::string & b)
4476 return concat(a,
'/', detail::escape(b));
4478 return concat(
'(', str,
") ");
4480 static_cast<void>(leaf_element);
4487 std::runtime_error
m;
4504 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value,
int> = 0>
4507 const std::string w = concat(exception::name(
"parse_error", id_),
"parse error",
4508 position_string(pos),
": ", exception::diagnostics(context), what_arg);
4512 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value,
int> = 0>
4513 static parse_error create(
int id_, std::size_t byte_,
const std::string& what_arg, BasicJsonContext context)
4515 const std::string w = concat(exception::name(
"parse_error", id_),
"parse error",
4516 (byte_ != 0 ? (concat(
" at byte ", std::to_string(byte_))) :
""),
4517 ": ",
exception::diagnostics(context), what_arg);
4518 return {id_, byte_, w.c_str()};
4533 parse_error(
int id_, std::size_t byte_,
const char* what_arg)
4536 static std::string position_string(
const position_t& pos)
4538 return concat(
" at line ", std::to_string(pos.
lines_read + 1),
4548 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value,
int> = 0>
4549 static invalid_iterator create(
int id_,
const std::string& what_arg, BasicJsonContext context)
4551 const std::string w = concat(exception::name(
"invalid_iterator", id_), exception::diagnostics(context), what_arg);
4552 return {id_, w.c_str()};
4556 JSON_HEDLEY_NON_NULL(3)
4566 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value,
int> = 0>
4567 static type_error create(
int id_,
const std::string& what_arg, BasicJsonContext context)
4569 const std::string w = concat(exception::name(
"type_error", id_), exception::diagnostics(context), what_arg);
4570 return {id_, w.c_str()};
4574 JSON_HEDLEY_NON_NULL(3)
4583 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value,
int> = 0>
4584 static out_of_range create(
int id_,
const std::string& what_arg, BasicJsonContext context)
4586 const std::string w = concat(exception::name(
"out_of_range", id_), exception::diagnostics(context), what_arg);
4587 return {id_, w.c_str()};
4591 JSON_HEDLEY_NON_NULL(3)
4600 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value,
int> = 0>
4601 static other_error create(
int id_,
const std::string& what_arg, BasicJsonContext context)
4603 const std::string w = concat(exception::name(
"other_error", id_), exception::diagnostics(context), what_arg);
4604 return {id_, w.c_str()};
4608 JSON_HEDLEY_NON_NULL(3)
4613NLOHMANN_JSON_NAMESPACE_END
4633NLOHMANN_JSON_NAMESPACE_BEGIN
4641NLOHMANN_JSON_NAMESPACE_END
4657#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4658#include <experimental/filesystem>
4659NLOHMANN_JSON_NAMESPACE_BEGIN
4662namespace std_fs = std::experimental::filesystem;
4664NLOHMANN_JSON_NAMESPACE_END
4665#elif JSON_HAS_FILESYSTEM
4666#include <filesystem>
4667NLOHMANN_JSON_NAMESPACE_BEGIN
4670namespace std_fs = std::filesystem;
4672NLOHMANN_JSON_NAMESPACE_END
4682NLOHMANN_JSON_NAMESPACE_BEGIN
4686template<
typename BasicJsonType>
4687inline void from_json(
const BasicJsonType& j,
typename std::nullptr_t& n)
4689 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4691 JSON_THROW(type_error::create(302, concat(
"type must be null, but is ", j.type_name()), &j));
4697template <
typename BasicJsonType,
typename ArithmeticType,
4698 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4699 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4701void get_arithmetic_value(
const BasicJsonType& j, ArithmeticType& val)
4703 switch (
static_cast<value_t>(j))
4707 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4712 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4717 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4729 JSON_THROW(type_error::create(302, concat(
"type must be number, but is ", j.type_name()), &j));
4733template<
typename BasicJsonType>
4734inline void from_json(
const BasicJsonType& j,
typename BasicJsonType::boolean_t& b)
4736 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4738 JSON_THROW(type_error::create(302, concat(
"type must be boolean, but is ", j.type_name()), &j));
4740 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4743template<
typename BasicJsonType>
4744inline void from_json(
const BasicJsonType& j,
typename BasicJsonType::string_t& s)
4746 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4748 JSON_THROW(type_error::create(302, concat(
"type must be string, but is ", j.type_name()), &j));
4750 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4754 typename BasicJsonType,
typename StringType,
4756 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4757 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4758 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4759 && !is_json_ref<StringType>::value,
int > = 0 >
4760inline void from_json(
const BasicJsonType& j, StringType& s)
4762 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4764 JSON_THROW(type_error::create(302, concat(
"type must be string, but is ", j.type_name()), &j));
4767 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4770template<
typename BasicJsonType>
4771inline void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_float_t& val)
4773 get_arithmetic_value(j, val);
4776template<
typename BasicJsonType>
4777inline void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_unsigned_t& val)
4779 get_arithmetic_value(j, val);
4782template<
typename BasicJsonType>
4783inline void from_json(
const BasicJsonType& j,
typename BasicJsonType::number_integer_t& val)
4785 get_arithmetic_value(j, val);
4788#if !JSON_DISABLE_ENUM_SERIALIZATION
4789template<
typename BasicJsonType,
typename EnumType,
4790 enable_if_t<std::is_enum<EnumType>::value,
int> = 0>
4791inline void from_json(
const BasicJsonType& j, EnumType& e)
4793 typename std::underlying_type<EnumType>::type val;
4794 get_arithmetic_value(j, val);
4795 e =
static_cast<EnumType
>(val);
4800template<
typename BasicJsonType,
typename T,
typename Allocator,
4801 enable_if_t<is_getable<BasicJsonType, T>::value,
int> = 0>
4802inline void from_json(
const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4804 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4806 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
4809 std::transform(j.rbegin(), j.rend(),
4810 std::front_inserter(l), [](
const BasicJsonType & i)
4812 return i.template get<T>();
4817template<
typename BasicJsonType,
typename T,
4818 enable_if_t<is_getable<BasicJsonType, T>::value,
int> = 0>
4819inline void from_json(
const BasicJsonType& j, std::valarray<T>& l)
4821 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4823 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
4826 std::transform(j.begin(), j.end(), std::begin(l),
4827 [](
const BasicJsonType & elem)
4829 return elem.template get<T>();
4833template<
typename BasicJsonType,
typename T, std::
size_t N>
4834auto from_json(
const BasicJsonType& j, T (&arr)[N])
4835->
decltype(j.template get<T>(), void())
4837 for (std::size_t i = 0; i < N; ++i)
4839 arr[i] = j.at(i).template get<T>();
4843template<
typename BasicJsonType>
4844inline void from_json_array_impl(
const BasicJsonType& j,
typename BasicJsonType::array_t& arr, priority_tag<3> )
4846 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4849template<
typename BasicJsonType,
typename T, std::
size_t N>
4850auto from_json_array_impl(
const BasicJsonType& j, std::array<T, N>& arr,
4852->
decltype(j.template get<T>(), void())
4854 for (std::size_t i = 0; i < N; ++i)
4856 arr[i] = j.at(i).template get<T>();
4860template<
typename BasicJsonType,
typename ConstructibleArrayType,
4862 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4864auto from_json_array_impl(
const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> )
4866 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4867 j.template get<typename ConstructibleArrayType::value_type>(),
4872 ConstructibleArrayType ret;
4873 ret.reserve(j.size());
4874 std::transform(j.begin(), j.end(),
4875 std::inserter(ret, end(ret)), [](
const BasicJsonType & i)
4879 return i.template get<typename ConstructibleArrayType::value_type>();
4881 arr = std::move(ret);
4884template<
typename BasicJsonType,
typename ConstructibleArrayType,
4886 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4888inline void from_json_array_impl(
const BasicJsonType& j, ConstructibleArrayType& arr,
4893 ConstructibleArrayType ret;
4895 j.begin(), j.end(), std::inserter(ret, end(ret)),
4896 [](
const BasicJsonType & i)
4900 return i.template get<typename ConstructibleArrayType::value_type>();
4902 arr = std::move(ret);
4905template <
typename BasicJsonType,
typename ConstructibleArrayType,
4907 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4908 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4909 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4910 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4911 !is_basic_json<ConstructibleArrayType>::value,
4913auto from_json(
const BasicJsonType& j, ConstructibleArrayType& arr)
4914->
decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4915j.template get<typename ConstructibleArrayType::value_type>(),
4918 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4920 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
4923 from_json_array_impl(j, arr, priority_tag<3> {});
4926template <
typename BasicJsonType,
typename T, std::size_t... Idx >
4927std::array<T,
sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4928 identity_tag<std::array<T,
sizeof...(Idx)>> , index_sequence<Idx...> )
4930 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4933template <
typename BasicJsonType,
typename T, std::
size_t N >
4934auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4935->
decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4937 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4939 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
4942 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4945template<
typename BasicJsonType>
4946inline void from_json(
const BasicJsonType& j,
typename BasicJsonType::binary_t& bin)
4948 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4950 JSON_THROW(type_error::create(302, concat(
"type must be binary, but is ", j.type_name()), &j));
4953 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4956template<
typename BasicJsonType,
typename ConstructibleObjectType,
4957 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value,
int> = 0>
4958inline void from_json(
const BasicJsonType& j, ConstructibleObjectType& obj)
4960 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4962 JSON_THROW(type_error::create(302, concat(
"type must be object, but is ", j.type_name()), &j));
4965 ConstructibleObjectType ret;
4966 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4967 using value_type =
typename ConstructibleObjectType::value_type;
4969 inner_object->begin(), inner_object->end(),
4970 std::inserter(ret, ret.begin()),
4971 [](
typename BasicJsonType::object_t::value_type
const & p)
4973 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4975 obj = std::move(ret);
4982template <
typename BasicJsonType,
typename ArithmeticType,
4984 std::is_arithmetic<ArithmeticType>::value&&
4985 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4986 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4987 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4988 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4990inline void from_json(
const BasicJsonType& j, ArithmeticType& val)
4992 switch (
static_cast<value_t>(j))
4996 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5001 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5006 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5011 val =
static_cast<ArithmeticType
>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5022 JSON_THROW(type_error::create(302, concat(
"type must be number, but is ", j.type_name()), &j));
5026template<
typename BasicJsonType,
typename... Args, std::size_t... Idx>
5027std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> )
5029 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).
template get<Args>()...);
5032template <
typename BasicJsonType,
class A1,
class A2 >
5033std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> , priority_tag<0> )
5035 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5036 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5039template<
typename BasicJsonType,
typename A1,
typename A2>
5040inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> )
5042 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5045template<
typename BasicJsonType,
typename... Args>
5046std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> , priority_tag<2> )
5048 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5051template<
typename BasicJsonType,
typename... Args>
5052inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> )
5054 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5057template<
typename BasicJsonType,
typename TupleRelated>
5058auto from_json(BasicJsonType&& j, TupleRelated&& t)
5059->
decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5061 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5063 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
5066 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5069template <
typename BasicJsonType,
typename Key,
typename Value,
typename Compare,
typename Allocator,
5070 typename = enable_if_t < !std::is_constructible <
5071 typename BasicJsonType::string_t, Key >
::value >>
5072inline void from_json(
const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5074 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5076 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
5079 for (
const auto& p : j)
5081 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5083 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", p.type_name()), &j));
5085 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5089template <
typename BasicJsonType,
typename Key,
typename Value,
typename Hash,
typename KeyEqual,
typename Allocator,
5090 typename = enable_if_t < !std::is_constructible <
5091 typename BasicJsonType::string_t, Key >
::value >>
5092inline void from_json(
const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5094 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5096 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", j.type_name()), &j));
5099 for (
const auto& p : j)
5101 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5103 JSON_THROW(type_error::create(302, concat(
"type must be array, but is ", p.type_name()), &j));
5105 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5109#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5110template<
typename BasicJsonType>
5111inline void from_json(
const BasicJsonType& j, std_fs::path& p)
5113 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5115 JSON_THROW(type_error::create(302, concat(
"type must be string, but is ", j.type_name()), &j));
5117 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5123 template<
typename BasicJsonType,
typename T>
5124 auto operator()(
const BasicJsonType& j, T&& val)
const
5125 noexcept(
noexcept(from_json(j, std::forward<T>(val))))
5126 ->
decltype(from_json(j, std::forward<T>(val)))
5128 return from_json(j, std::forward<T>(val));
5134#ifndef JSON_HAS_CPP_17
5141JSON_INLINE_VARIABLE
constexpr const auto& from_json =
5143#ifndef JSON_HAS_CPP_17
5147NLOHMANN_JSON_NAMESPACE_END
5164#include <type_traits>
5197NLOHMANN_JSON_NAMESPACE_BEGIN
5201template<
typename string_type>
5202void int_to_string( string_type& target, std::size_t
value )
5205 using std::to_string;
5206 target = to_string(
value);
5211 using difference_type = std::ptrdiff_t;
5215 using iterator_category = std::input_iterator_tag;
5216 using string_type =
typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().
key() ) >::type >::type;
5233 noexcept(std::is_nothrow_move_constructible<IteratorType>::
value
5234 && std::is_nothrow_default_constructible<string_type>::
value)
5239 iteration_proxy_value(iteration_proxy_value
const&) =
default;
5240 iteration_proxy_value& operator=(iteration_proxy_value
const&) =
default;
5242 iteration_proxy_value(iteration_proxy_value&&)
5243 noexcept(std::is_nothrow_move_constructible<IteratorType>::
value
5244 && std::is_nothrow_move_constructible<string_type>::
value) = default;
5245 iteration_proxy_value& operator=(iteration_proxy_value&&)
5246 noexcept(std::is_nothrow_move_assignable<IteratorType>::
value
5247 && std::is_nothrow_move_assignable<string_type>::
value) = default;
5248 ~iteration_proxy_value() = default;
5286 const string_type&
key()
const
5288 JSON_ASSERT(
anchor.m_object !=
nullptr);
5290 switch (
anchor.m_object->type())
5322 typename IteratorType::reference
value()
const
5364template<std::
size_t N,
typename IteratorType, enable_if_t<N == 0,
int> = 0>
5365auto get(
const nlohmann::detail::iteration_proxy_value<IteratorType>& i) ->
decltype(i.key())
5372template<std::
size_t N,
typename IteratorType, enable_if_t<N == 1,
int> = 0>
5373auto get(
const nlohmann::detail::iteration_proxy_value<IteratorType>& i) ->
decltype(i.value())
5379NLOHMANN_JSON_NAMESPACE_END
5388#if defined(__clang__)
5390 #pragma clang diagnostic push
5391 #pragma clang diagnostic ignored "-Wmismatched-tags"
5393template<
typename IteratorType>
5394class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
5395 :
public std::integral_constant<std::size_t, 2> {};
5397template<std::
size_t N,
typename IteratorType>
5398class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
5401 using type =
decltype(
5402 get<N>(std::declval <
5403 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5405#if defined(__clang__)
5406 #pragma clang diagnostic pop
5412 template <
typename IteratorType>
5413 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> =
true;
5427NLOHMANN_JSON_NAMESPACE_BEGIN
5447 template<
typename BasicJsonType>
5448 static void construct(BasicJsonType& j,
typename BasicJsonType::boolean_t b)
noexcept
5450 j.m_data.m_value.destroy(j.m_data.m_type);
5452 j.m_data.m_value = b;
5453 j.assert_invariant();
5460 template<
typename BasicJsonType>
5461 static void construct(BasicJsonType& j,
const typename BasicJsonType::string_t& s)
5463 j.m_data.m_value.destroy(j.m_data.m_type);
5465 j.m_data.m_value = s;
5466 j.assert_invariant();
5469 template<
typename BasicJsonType>
5470 static void construct(BasicJsonType& j,
typename BasicJsonType::string_t&& s)
5472 j.m_data.m_value.destroy(j.m_data.m_type);
5474 j.m_data.m_value = std::move(s);
5475 j.assert_invariant();
5478 template <
typename BasicJsonType,
typename CompatibleStringType,
5479 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5481 static void construct(BasicJsonType& j,
const CompatibleStringType& str)
5483 j.m_data.m_value.destroy(j.m_data.m_type);
5485 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5486 j.assert_invariant();
5493 template<
typename BasicJsonType>
5494 static void construct(BasicJsonType& j,
const typename BasicJsonType::binary_t& b)
5496 j.m_data.m_value.destroy(j.m_data.m_type);
5498 j.m_data.m_value =
typename BasicJsonType::binary_t(b);
5499 j.assert_invariant();
5502 template<
typename BasicJsonType>
5503 static void construct(BasicJsonType& j,
typename BasicJsonType::binary_t&& b)
5505 j.m_data.m_value.destroy(j.m_data.m_type);
5507 j.m_data.m_value =
typename BasicJsonType::binary_t(std::move(b));
5508 j.assert_invariant();
5515 template<
typename BasicJsonType>
5516 static void construct(BasicJsonType& j,
typename BasicJsonType::number_float_t val)
noexcept
5518 j.m_data.m_value.destroy(j.m_data.m_type);
5520 j.m_data.m_value = val;
5521 j.assert_invariant();
5528 template<
typename BasicJsonType>
5529 static void construct(BasicJsonType& j,
typename BasicJsonType::number_unsigned_t val)
noexcept
5531 j.m_data.m_value.destroy(j.m_data.m_type);
5533 j.m_data.m_value = val;
5534 j.assert_invariant();
5541 template<
typename BasicJsonType>
5542 static void construct(BasicJsonType& j,
typename BasicJsonType::number_integer_t val)
noexcept
5544 j.m_data.m_value.destroy(j.m_data.m_type);
5546 j.m_data.m_value = val;
5547 j.assert_invariant();
5554 template<
typename BasicJsonType>
5555 static void construct(BasicJsonType& j,
const typename BasicJsonType::array_t& arr)
5557 j.m_data.m_value.destroy(j.m_data.m_type);
5559 j.m_data.m_value = arr;
5561 j.assert_invariant();
5564 template<
typename BasicJsonType>
5565 static void construct(BasicJsonType& j,
typename BasicJsonType::array_t&& arr)
5567 j.m_data.m_value.destroy(j.m_data.m_type);
5569 j.m_data.m_value = std::move(arr);
5571 j.assert_invariant();
5574 template <
typename BasicJsonType,
typename CompatibleArrayType,
5575 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5577 static void construct(BasicJsonType& j,
const CompatibleArrayType& arr)
5582 j.m_data.m_value.destroy(j.m_data.m_type);
5584 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5586 j.assert_invariant();
5589 template<
typename BasicJsonType>
5590 static void construct(BasicJsonType& j,
const std::vector<bool>& arr)
5592 j.m_data.m_value.destroy(j.m_data.m_type);
5595 j.m_data.m_value.array->reserve(arr.size());
5596 for (
const bool x : arr)
5598 j.m_data.m_value.array->push_back(x);
5599 j.set_parent(j.m_data.m_value.array->back());
5601 j.assert_invariant();
5604 template<
typename BasicJsonType,
typename T,
5605 enable_if_t<std::is_convertible<T, BasicJsonType>::value,
int> = 0>
5606 static void construct(BasicJsonType& j,
const std::valarray<T>& arr)
5608 j.m_data.m_value.destroy(j.m_data.m_type);
5611 j.m_data.m_value.array->resize(arr.size());
5614 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5617 j.assert_invariant();
5624 template<
typename BasicJsonType>
5625 static void construct(BasicJsonType& j,
const typename BasicJsonType::object_t& obj)
5627 j.m_data.m_value.destroy(j.m_data.m_type);
5629 j.m_data.m_value = obj;
5631 j.assert_invariant();
5634 template<
typename BasicJsonType>
5635 static void construct(BasicJsonType& j,
typename BasicJsonType::object_t&& obj)
5637 j.m_data.m_value.destroy(j.m_data.m_type);
5639 j.m_data.m_value = std::move(obj);
5641 j.assert_invariant();
5644 template <
typename BasicJsonType,
typename CompatibleObjectType,
5645 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value,
int > = 0 >
5646 static void construct(BasicJsonType& j,
const CompatibleObjectType& obj)
5651 j.m_data.m_value.destroy(j.m_data.m_type);
5653 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5655 j.assert_invariant();
5663template<
typename BasicJsonType,
typename T,
5664 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value,
int> = 0>
5665inline void to_json(BasicJsonType& j, T b)
noexcept
5670template <
typename BasicJsonType,
typename BoolRef,
5672 ((std::is_same<std::vector<bool>::reference, BoolRef>
::value
5673 && !std::is_same <std::vector<bool>::reference,
typename BasicJsonType::boolean_t&>
::value)
5674 || (std::is_same<std::vector<bool>::const_reference, BoolRef>
::value
5675 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5676 typename BasicJsonType::boolean_t >
::value))
5677 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value,
int > = 0 >
5678inline void to_json(BasicJsonType& j,
const BoolRef& b)
noexcept
5680 external_constructor<value_t::boolean>::construct(j,
static_cast<typename BasicJsonType::boolean_t
>(b));
5683template<
typename BasicJsonType,
typename CompatibleString,
5684 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value,
int> = 0>
5685inline void to_json(BasicJsonType& j,
const CompatibleString& s)
5687 external_constructor<value_t::string>::construct(j, s);
5690template<
typename BasicJsonType>
5691inline void to_json(BasicJsonType& j,
typename BasicJsonType::string_t&& s)
5693 external_constructor<value_t::string>::construct(j, std::move(s));
5696template<
typename BasicJsonType,
typename FloatType,
5697 enable_if_t<std::is_floating_point<FloatType>::value,
int> = 0>
5698inline void to_json(BasicJsonType& j, FloatType val)
noexcept
5700 external_constructor<value_t::number_float>::construct(j,
static_cast<typename BasicJsonType::number_float_t
>(val));
5703template<
typename BasicJsonType,
typename CompatibleNumberUnsignedType,
5704 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value,
int> = 0>
5705inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val)
noexcept
5707 external_constructor<value_t::number_unsigned>::construct(j,
static_cast<typename BasicJsonType::number_unsigned_t
>(val));
5710template<
typename BasicJsonType,
typename CompatibleNumberIntegerType,
5711 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value,
int> = 0>
5712inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val)
noexcept
5714 external_constructor<value_t::number_integer>::construct(j,
static_cast<typename BasicJsonType::number_integer_t
>(val));
5717#if !JSON_DISABLE_ENUM_SERIALIZATION
5718template<
typename BasicJsonType,
typename EnumType,
5719 enable_if_t<std::is_enum<EnumType>::value,
int> = 0>
5720inline void to_json(BasicJsonType& j, EnumType e)
noexcept
5722 using underlying_type =
typename std::underlying_type<EnumType>::type;
5723 external_constructor<value_t::number_integer>::construct(j,
static_cast<underlying_type
>(e));
5727template<
typename BasicJsonType>
5728inline void to_json(BasicJsonType& j,
const std::vector<bool>& e)
5730 external_constructor<value_t::array>::construct(j, e);
5733template <
typename BasicJsonType,
typename CompatibleArrayType,
5734 enable_if_t < is_compatible_array_type<BasicJsonType,
5736 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5737 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5738 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5739 !is_basic_json<CompatibleArrayType>::value,
5741inline void to_json(BasicJsonType& j,
const CompatibleArrayType& arr)
5743 external_constructor<value_t::array>::construct(j, arr);
5746template<
typename BasicJsonType>
5747inline void to_json(BasicJsonType& j,
const typename BasicJsonType::binary_t& bin)
5749 external_constructor<value_t::binary>::construct(j, bin);
5752template<
typename BasicJsonType,
typename T,
5753 enable_if_t<std::is_convertible<T, BasicJsonType>::value,
int> = 0>
5754inline void to_json(BasicJsonType& j,
const std::valarray<T>& arr)
5756 external_constructor<value_t::array>::construct(j, std::move(arr));
5759template<
typename BasicJsonType>
5760inline void to_json(BasicJsonType& j,
typename BasicJsonType::array_t&& arr)
5762 external_constructor<value_t::array>::construct(j, std::move(arr));
5765template <
typename BasicJsonType,
typename CompatibleObjectType,
5766 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value,
int > = 0 >
5767inline void to_json(BasicJsonType& j,
const CompatibleObjectType& obj)
5769 external_constructor<value_t::object>::construct(j, obj);
5772template<
typename BasicJsonType>
5773inline void to_json(BasicJsonType& j,
typename BasicJsonType::object_t&& obj)
5775 external_constructor<value_t::object>::construct(j, std::move(obj));
5779 typename BasicJsonType,
typename T, std::size_t N,
5780 enable_if_t < !std::is_constructible<
typename BasicJsonType::string_t,
5783inline void to_json(BasicJsonType& j,
const T(&arr)[N])
5785 external_constructor<value_t::array>::construct(j, arr);
5788template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value,
int > = 0 >
5789inline void to_json(BasicJsonType& j,
const std::pair<T1, T2>& p)
5791 j = { p.first, p.second };
5795template<
typename BasicJsonType,
typename T,
5796 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>
::value,
int> = 0>
5797inline void to_json(BasicJsonType& j,
const T& b)
5799 j = { {b.key(), b.value()} };
5802template<
typename BasicJsonType,
typename Tuple, std::size_t... Idx>
5803inline void to_json_tuple_impl(BasicJsonType& j,
const Tuple& t, index_sequence<Idx...> )
5805 j = { std::get<Idx>(t)... };
5808template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value,
int > = 0>
5809inline void to_json(BasicJsonType& j,
const T& t)
5811 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5814#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5815template<
typename BasicJsonType>
5816inline void to_json(BasicJsonType& j,
const std_fs::path& p)
5824 template<
typename BasicJsonType,
typename T>
5825 auto operator()(BasicJsonType& j, T&& val)
const noexcept(
noexcept(to_json(j, std::forward<T>(val))))
5826 ->
decltype(to_json(j, std::forward<T>(val)), void())
5828 return to_json(j, std::forward<T>(val));
5833#ifndef JSON_HAS_CPP_17
5840JSON_INLINE_VARIABLE
constexpr const auto& to_json =
5842#ifndef JSON_HAS_CPP_17
5846NLOHMANN_JSON_NAMESPACE_END
5851NLOHMANN_JSON_NAMESPACE_BEGIN
5854template<
typename ValueType,
typename>
5859 template<
typename BasicJsonType,
typename TargetType = ValueType>
5860 static auto from_json(BasicJsonType && j, TargetType& val)
noexcept(
5861 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5862 ->
decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5864 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5869 template<
typename BasicJsonType,
typename TargetType = ValueType>
5879 template<
typename BasicJsonType,
typename TargetType = ValueType>
5880 static auto to_json(BasicJsonType& j, TargetType && val)
noexcept(
5881 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5882 ->
decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5884 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5888NLOHMANN_JSON_NAMESPACE_END
5908NLOHMANN_JSON_NAMESPACE_BEGIN
5912template<
typename BinaryType>
5916 using container_type = BinaryType;
5917 using subtype_type = std::uint64_t;
5931 : container_type(std::move(b))
5937 , m_subtype(subtype_)
5938 , m_has_subtype(
true)
5943 : container_type(std::move(b))
5944 , m_subtype(subtype_)
5945 , m_has_subtype(
true)
5950 return std::tie(
static_cast<const BinaryType&
>(*
this), m_subtype, m_has_subtype) ==
5951 std::tie(
static_cast<const BinaryType&
>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5956 return !(rhs == *
this);
5963 m_subtype = subtype_;
5964 m_has_subtype =
true;
5971 return m_has_subtype ? m_subtype :
static_cast<subtype_type
>(-1);
5978 return m_has_subtype;
5986 m_has_subtype =
false;
5990 subtype_type m_subtype = 0;
5991 bool m_has_subtype =
false;
5994NLOHMANN_JSON_NAMESPACE_END
6015#include <functional>
6022NLOHMANN_JSON_NAMESPACE_BEGIN
6027inline std::size_t combine(std::size_t seed, std::size_t h)
noexcept
6029 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6044template<
typename BasicJsonType>
6045std::size_t
hash(
const BasicJsonType& j)
6047 using string_t =
typename BasicJsonType::string_t;
6048 using number_integer_t =
typename BasicJsonType::number_integer_t;
6049 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
6050 using number_float_t =
typename BasicJsonType::number_float_t;
6052 const auto type =
static_cast<std::size_t
>(j.type());
6055 case BasicJsonType::value_t::null:
6056 case BasicJsonType::value_t::discarded:
6058 return combine(type, 0);
6061 case BasicJsonType::value_t::object:
6063 auto seed = combine(type, j.size());
6064 for (
const auto& element : j.items())
6066 const auto h = std::hash<string_t> {}(element.key());
6067 seed = combine(seed, h);
6068 seed = combine(seed,
hash(element.value()));
6073 case BasicJsonType::value_t::array:
6075 auto seed = combine(type, j.size());
6076 for (
const auto& element : j)
6078 seed = combine(seed,
hash(element));
6083 case BasicJsonType::value_t::string:
6085 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6086 return combine(type, h);
6089 case BasicJsonType::value_t::boolean:
6091 const auto h = std::hash<bool> {}(j.template get<bool>());
6092 return combine(type, h);
6095 case BasicJsonType::value_t::number_integer:
6097 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6098 return combine(type, h);
6101 case BasicJsonType::value_t::number_unsigned:
6103 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6104 return combine(type, h);
6107 case BasicJsonType::value_t::number_float:
6109 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6110 return combine(type, h);
6113 case BasicJsonType::value_t::binary:
6115 auto seed = combine(type, j.get_binary().size());
6116 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6117 seed = combine(seed, h);
6118 seed = combine(seed,
static_cast<std::size_t
>(j.get_binary().subtype()));
6119 for (
const auto byte : j.get_binary())
6121 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6133NLOHMANN_JSON_NAMESPACE_END
6179#include <type_traits>
6194NLOHMANN_JSON_NAMESPACE_BEGIN
6213 using char_type = char;
6215 JSON_HEDLEY_NON_NULL(2)
6219 JSON_ASSERT(
m_file !=
nullptr);
6229 std::char_traits<char>::int_type get_character()
noexcept
6231 return std::fgetc(
m_file);
6251 using char_type = char;
6259 is->clear(
is->rdstate() & std::ios::eofbit);
6264 :
is(&i), sb(i.rdbuf())
6273 :
is(rhs.is), sb(rhs.sb)
6282 std::char_traits<char>::int_type get_character()
6284 auto res = sb->sbumpc();
6286 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6288 is->clear(
is->rdstate() | std::ios::eofbit);
6295 std::istream*
is =
nullptr;
6296 std::streambuf* sb =
nullptr;
6302template<
typename IteratorType>
6306 using char_type =
typename std::iterator_traits<IteratorType>::value_type;
6309 : current(std::move(first)), end(std::move(last))
6314 if (JSON_HEDLEY_LIKELY(current != end))
6317 std::advance(current, 1);
6325 IteratorType current;
6328 template<
typename BaseInputAdapter,
size_t T>
6333 return current == end;
6337template<
typename BaseInputAdapter,
size_t T>
6340template<
typename BaseInputAdapter>
6344 static void fill_buffer(BaseInputAdapter& input,
6345 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6346 size_t& utf8_bytes_index,
6347 size_t& utf8_bytes_filled)
6349 utf8_bytes_index = 0;
6351 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6353 utf8_bytes[0] = std::char_traits<char>::eof();
6354 utf8_bytes_filled = 1;
6359 const auto wc = input.get_character();
6364 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(wc);
6365 utf8_bytes_filled = 1;
6367 else if (wc <= 0x7FF)
6369 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(0xC0u | ((
static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6370 utf8_bytes[1] =
static_cast<std::char_traits<char>::int_type
>(0x80u | (
static_cast<unsigned int>(wc) & 0x3Fu));
6371 utf8_bytes_filled = 2;
6373 else if (wc <= 0xFFFF)
6375 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(0xE0u | ((
static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6376 utf8_bytes[1] =
static_cast<std::char_traits<char>::int_type
>(0x80u | ((
static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6377 utf8_bytes[2] =
static_cast<std::char_traits<char>::int_type
>(0x80u | (
static_cast<unsigned int>(wc) & 0x3Fu));
6378 utf8_bytes_filled = 3;
6380 else if (wc <= 0x10FFFF)
6382 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(0xF0u | ((
static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6383 utf8_bytes[1] =
static_cast<std::char_traits<char>::int_type
>(0x80u | ((
static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6384 utf8_bytes[2] =
static_cast<std::char_traits<char>::int_type
>(0x80u | ((
static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6385 utf8_bytes[3] =
static_cast<std::char_traits<char>::int_type
>(0x80u | (
static_cast<unsigned int>(wc) & 0x3Fu));
6386 utf8_bytes_filled = 4;
6391 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(wc);
6392 utf8_bytes_filled = 1;
6398template<
typename BaseInputAdapter>
6402 static void fill_buffer(BaseInputAdapter& input,
6403 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6404 size_t& utf8_bytes_index,
6405 size_t& utf8_bytes_filled)
6407 utf8_bytes_index = 0;
6409 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6411 utf8_bytes[0] = std::char_traits<char>::eof();
6412 utf8_bytes_filled = 1;
6417 const auto wc = input.get_character();
6422 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(wc);
6423 utf8_bytes_filled = 1;
6425 else if (wc <= 0x7FF)
6427 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(0xC0u | ((
static_cast<unsigned int>(wc) >> 6u)));
6428 utf8_bytes[1] =
static_cast<std::char_traits<char>::int_type
>(0x80u | (
static_cast<unsigned int>(wc) & 0x3Fu));
6429 utf8_bytes_filled = 2;
6431 else if (0xD800 > wc || wc >= 0xE000)
6433 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(0xE0u | ((
static_cast<unsigned int>(wc) >> 12u)));
6434 utf8_bytes[1] =
static_cast<std::char_traits<char>::int_type
>(0x80u | ((
static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6435 utf8_bytes[2] =
static_cast<std::char_traits<char>::int_type
>(0x80u | (
static_cast<unsigned int>(wc) & 0x3Fu));
6436 utf8_bytes_filled = 3;
6440 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6442 const auto wc2 =
static_cast<unsigned int>(input.get_character());
6443 const auto charcode = 0x10000u + (((
static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6444 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(0xF0u | (charcode >> 18u));
6445 utf8_bytes[1] =
static_cast<std::char_traits<char>::int_type
>(0x80u | ((charcode >> 12u) & 0x3Fu));
6446 utf8_bytes[2] =
static_cast<std::char_traits<char>::int_type
>(0x80u | ((charcode >> 6u) & 0x3Fu));
6447 utf8_bytes[3] =
static_cast<std::char_traits<char>::int_type
>(0x80u | (charcode & 0x3Fu));
6448 utf8_bytes_filled = 4;
6452 utf8_bytes[0] =
static_cast<std::char_traits<char>::int_type
>(wc);
6453 utf8_bytes_filled = 1;
6461template<
typename BaseInputAdapter,
typename W
ideCharType>
6465 using char_type = char;
6468 : base_adapter(base) {}
6470 typename std::char_traits<char>::int_type get_character()
noexcept
6475 fill_buffer<sizeof(WideCharType)>();
6488 BaseInputAdapter base_adapter;
6497 std::array<std::char_traits<char>::int_type, 4>
utf8_bytes = {{0, 0, 0, 0}};
6505template<
typename IteratorType,
typename Enable =
void>
6508 using iterator_type = IteratorType;
6509 using char_type =
typename std::iterator_traits<iterator_type>::value_type;
6512 static adapter_type create(IteratorType first, IteratorType last)
6514 return adapter_type(std::move(first), std::move(last));
6521 using value_type =
typename std::iterator_traits<T>::value_type;
6524 value =
sizeof(value_type) > 1
6528template<
typename IteratorType>
6531 using iterator_type = IteratorType;
6532 using char_type =
typename std::iterator_traits<iterator_type>::value_type;
6536 static adapter_type create(IteratorType first, IteratorType last)
6538 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6543template<
typename IteratorType>
6544typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6547 return factory_type::create(first, last);
6554namespace container_input_adapter_factory_impl
6560template<
typename ContainerType,
typename Enable =
void>
6563template<
typename ContainerType>
6565 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6567 using adapter_type =
decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6569 static adapter_type create(
const ContainerType& container)
6571 return input_adapter(begin(container), end(container));
6577template<
typename ContainerType>
6585inline file_input_adapter input_adapter(std::FILE* file)
6587 return file_input_adapter(file);
6590inline input_stream_adapter input_adapter(std::istream& stream)
6592 return input_stream_adapter(stream);
6595inline input_stream_adapter input_adapter(std::istream&& stream)
6597 return input_stream_adapter(stream);
6601using contiguous_bytes_input_adapter =
decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6604template <
typename CharT,
6605 typename std::enable_if <
6606 std::is_pointer<CharT>::value&&
6607 !std::is_array<CharT>::value&&
6608 std::is_integral<typename std::remove_pointer<CharT>::type>
::value&&
6609 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
6611contiguous_bytes_input_adapter input_adapter(CharT b)
6613 auto length = std::strlen(
reinterpret_cast<const char*
>(b));
6614 const auto* ptr =
reinterpret_cast<const char*
>(b);
6615 return input_adapter(ptr, ptr + length);
6618template<
typename T, std::
size_t N>
6619auto input_adapter(T (&
array)[N]) ->
decltype(input_adapter(
array,
array + N))
6630 template <
typename CharT,
6631 typename std::enable_if <
6632 std::is_pointer<CharT>::value&&
6633 std::is_integral<typename std::remove_pointer<CharT>::type>
::value&&
6634 sizeof(
typename std::remove_pointer<CharT>::type) == 1,
6637 : ia(
reinterpret_cast<const char*
>(b),
reinterpret_cast<const char*
>(b) + l) {}
6639 template<
class IteratorType,
6640 typename std::enable_if<
6641 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>
::value,
6644 : ia(input_adapter(first, last)) {}
6646 contiguous_bytes_input_adapter&& get()
6648 return std::move(ia);
6652 contiguous_bytes_input_adapter ia;
6656NLOHMANN_JSON_NAMESPACE_END
6681NLOHMANN_JSON_NAMESPACE_BEGIN
6691template<
typename BasicJsonType>
6694 using number_integer_t =
typename BasicJsonType::number_integer_t;
6695 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
6696 using number_float_t =
typename BasicJsonType::number_float_t;
6697 using string_t =
typename BasicJsonType::string_t;
6698 using binary_t =
typename BasicJsonType::binary_t;
6765 virtual bool key(string_t& val) = 0;
6795 const std::string& last_token,
6821template<
typename BasicJsonType>
6825 using number_integer_t =
typename BasicJsonType::number_integer_t;
6826 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
6827 using number_float_t =
typename BasicJsonType::number_float_t;
6828 using string_t =
typename BasicJsonType::string_t;
6829 using binary_t =
typename BasicJsonType::binary_t;
6837 : root(r), allow_exceptions(allow_exceptions_)
6849 handle_value(
nullptr);
6853 bool boolean(
bool val)
6871 bool number_float(number_float_t val,
const string_t& )
6877 bool string(string_t& val)
6883 bool binary(binary_t& val)
6885 handle_value(std::move(val));
6889 bool start_object(std::size_t len)
6891 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6893 if (JSON_HEDLEY_UNLIKELY(len !=
static_cast<std::size_t
>(-1) && len > ref_stack.back()->max_size()))
6895 JSON_THROW(out_of_range::create(408, concat(
"excessive object size: ", std::to_string(len)), ref_stack.back()));
6901 bool key(string_t& val)
6903 JSON_ASSERT(!ref_stack.empty());
6904 JSON_ASSERT(ref_stack.back()->is_object());
6907 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6913 JSON_ASSERT(!ref_stack.empty());
6914 JSON_ASSERT(ref_stack.back()->is_object());
6916 ref_stack.back()->set_parents();
6917 ref_stack.pop_back();
6921 bool start_array(std::size_t len)
6923 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6925 if (JSON_HEDLEY_UNLIKELY(len !=
static_cast<std::size_t
>(-1) && len > ref_stack.back()->max_size()))
6927 JSON_THROW(out_of_range::create(408, concat(
"excessive array size: ", std::to_string(len)), ref_stack.back()));
6935 JSON_ASSERT(!ref_stack.empty());
6936 JSON_ASSERT(ref_stack.back()->is_array());
6938 ref_stack.back()->set_parents();
6939 ref_stack.pop_back();
6943 template<
class Exception>
6944 bool parse_error(std::size_t ,
const std::string& ,
6945 const Exception& ex)
6948 static_cast<void>(ex);
6949 if (allow_exceptions)
6956 constexpr bool is_errored()
const
6968 template<
typename Value>
6969 JSON_HEDLEY_RETURNS_NON_NULL
6972 if (ref_stack.empty())
6974 root = BasicJsonType(std::forward<Value>(v));
6978 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6980 if (ref_stack.back()->is_array())
6982 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6983 return &(ref_stack.back()->m_data.m_value.array->back());
6986 JSON_ASSERT(ref_stack.back()->is_object());
6987 JSON_ASSERT(object_element);
6988 *object_element = BasicJsonType(std::forward<Value>(v));
6989 return object_element;
6995 std::vector<BasicJsonType*> ref_stack {};
6997 BasicJsonType* object_element =
nullptr;
6999 bool errored =
false;
7001 const bool allow_exceptions =
true;
7004template<
typename BasicJsonType>
7008 using number_integer_t =
typename BasicJsonType::number_integer_t;
7009 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
7010 using number_float_t =
typename BasicJsonType::number_float_t;
7011 using string_t =
typename BasicJsonType::string_t;
7012 using binary_t =
typename BasicJsonType::binary_t;
7013 using parser_callback_t =
typename BasicJsonType::parser_callback_t;
7014 using parse_event_t =
typename BasicJsonType::parse_event_t;
7017 const parser_callback_t cb,
7018 const bool allow_exceptions_ =
true)
7019 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
7021 keep_stack.push_back(
true);
7033 handle_value(
nullptr);
7055 bool number_float(number_float_t val,
const string_t& )
7061 bool string(string_t& val)
7067 bool binary(binary_t& val)
7069 handle_value(std::move(val));
7073 bool start_object(std::size_t len)
7076 const bool keep = callback(
static_cast<int>(ref_stack.size()), parse_event_t::object_start,
discarded);
7077 keep_stack.push_back(keep);
7079 auto val = handle_value(BasicJsonType::value_t::object,
true);
7080 ref_stack.push_back(val.second);
7083 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len !=
static_cast<std::size_t
>(-1) && len > ref_stack.back()->max_size()))
7085 JSON_THROW(out_of_range::create(408, concat(
"excessive object size: ", std::to_string(len)), ref_stack.back()));
7091 bool key(string_t& val)
7093 BasicJsonType k = BasicJsonType(val);
7096 const bool keep = callback(
static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7097 key_keep_stack.push_back(keep);
7100 if (keep && ref_stack.back())
7102 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) =
discarded);
7110 if (ref_stack.back())
7112 if (!callback(
static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7119 ref_stack.back()->set_parents();
7123 JSON_ASSERT(!ref_stack.empty());
7124 JSON_ASSERT(!keep_stack.empty());
7125 ref_stack.pop_back();
7126 keep_stack.pop_back();
7128 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7131 for (
auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7133 if (it->is_discarded())
7135 ref_stack.back()->erase(it);
7144 bool start_array(std::size_t len)
7146 const bool keep = callback(
static_cast<int>(ref_stack.size()), parse_event_t::array_start,
discarded);
7147 keep_stack.push_back(keep);
7149 auto val = handle_value(BasicJsonType::value_t::array,
true);
7150 ref_stack.push_back(val.second);
7153 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len !=
static_cast<std::size_t
>(-1) && len > ref_stack.back()->max_size()))
7155 JSON_THROW(out_of_range::create(408, concat(
"excessive array size: ", std::to_string(len)), ref_stack.back()));
7165 if (ref_stack.back())
7167 keep = callback(
static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7170 ref_stack.back()->set_parents();
7179 JSON_ASSERT(!ref_stack.empty());
7180 JSON_ASSERT(!keep_stack.empty());
7181 ref_stack.pop_back();
7182 keep_stack.pop_back();
7185 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7187 ref_stack.back()->m_data.m_value.array->pop_back();
7193 template<
class Exception>
7194 bool parse_error(std::size_t ,
const std::string& ,
7195 const Exception& ex)
7198 static_cast<void>(ex);
7199 if (allow_exceptions)
7206 constexpr bool is_errored()
const
7227 template<
typename Value>
7228 std::pair<bool, BasicJsonType*>
handle_value(Value&& v,
const bool skip_callback =
false)
7230 JSON_ASSERT(!keep_stack.empty());
7234 if (!keep_stack.back())
7236 return {
false,
nullptr};
7240 auto value = BasicJsonType(std::forward<Value>(v));
7243 const bool keep = skip_callback || callback(
static_cast<int>(ref_stack.size()), parse_event_t::value,
value);
7248 return {
false,
nullptr};
7251 if (ref_stack.empty())
7253 root = std::move(
value);
7254 return {
true, & root};
7259 if (!ref_stack.back())
7261 return {
false,
nullptr};
7265 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7268 if (ref_stack.back()->is_array())
7270 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(
value));
7271 return {
true, & (ref_stack.back()->m_data.m_value.array->back())};
7275 JSON_ASSERT(ref_stack.back()->is_object());
7277 JSON_ASSERT(!key_keep_stack.empty());
7278 const bool store_element = key_keep_stack.back();
7279 key_keep_stack.pop_back();
7283 return {
false,
nullptr};
7286 JSON_ASSERT(object_element);
7287 *object_element = std::move(
value);
7288 return {
true, object_element};
7294 std::vector<BasicJsonType*> ref_stack {};
7296 std::vector<bool> keep_stack {};
7298 std::vector<bool> key_keep_stack {};
7300 BasicJsonType* object_element =
nullptr;
7302 bool errored =
false;
7304 const parser_callback_t callback =
nullptr;
7306 const bool allow_exceptions =
true;
7308 BasicJsonType
discarded = BasicJsonType::value_t::discarded;
7311template<
typename BasicJsonType>
7315 using number_integer_t =
typename BasicJsonType::number_integer_t;
7316 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
7317 using number_float_t =
typename BasicJsonType::number_float_t;
7318 using string_t =
typename BasicJsonType::string_t;
7319 using binary_t =
typename BasicJsonType::binary_t;
7356 bool start_object(std::size_t =
static_cast<std::size_t
>(-1))
7361 bool key(string_t& )
7371 bool start_array(std::size_t =
static_cast<std::size_t
>(-1))
7388NLOHMANN_JSON_NAMESPACE_END
7406#include <initializer_list>
7420NLOHMANN_JSON_NAMESPACE_BEGIN
7428template<
typename BasicJsonType>
7455 JSON_HEDLEY_RETURNS_NON_NULL
7461 case token_type::uninitialized:
7462 return "<uninitialized>";
7463 case token_type::literal_true:
7464 return "true literal";
7465 case token_type::literal_false:
7466 return "false literal";
7467 case token_type::literal_null:
7468 return "null literal";
7469 case token_type::value_string:
7470 return "string literal";
7471 case token_type::value_unsigned:
7472 case token_type::value_integer:
7473 case token_type::value_float:
7474 return "number literal";
7475 case token_type::begin_array:
7477 case token_type::begin_object:
7479 case token_type::end_array:
7481 case token_type::end_object:
7483 case token_type::name_separator:
7485 case token_type::value_separator:
7487 case token_type::parse_error:
7488 return "<parse error>";
7489 case token_type::end_of_input:
7490 return "end of input";
7491 case token_type::literal_or_value:
7492 return "'[', '{', or a literal";
7495 return "unknown token";
7505template<
typename BasicJsonType,
typename InputAdapterType>
7508 using number_integer_t =
typename BasicJsonType::number_integer_t;
7509 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
7510 using number_float_t =
typename BasicJsonType::number_float_t;
7511 using string_t =
typename BasicJsonType::string_t;
7512 using char_type =
typename InputAdapterType::char_type;
7518 explicit lexer(InputAdapterType&& adapter,
bool ignore_comments_ =
false) noexcept
7519 : ia(std::move(adapter))
7520 , ignore_comments(ignore_comments_)
7521 , decimal_point_char(
static_cast<char_int_type
>(get_decimal_point()))
7540 const auto* loc = localeconv();
7541 JSON_ASSERT(loc !=
nullptr);
7542 return (loc->decimal_point ==
nullptr) ?
'.' : *(loc->decimal_point);
7567 JSON_ASSERT(current ==
'u');
7570 const auto factors = { 12u, 8u, 4u, 0u };
7571 for (
const auto factor : factors)
7575 if (current >=
'0' && current <=
'9')
7577 codepoint +=
static_cast<int>((
static_cast<unsigned int>(current) - 0x30u) << factor);
7579 else if (current >=
'A' && current <=
'F')
7581 codepoint +=
static_cast<int>((
static_cast<unsigned int>(current) - 0x37u) << factor);
7583 else if (current >=
'a' && current <=
'f')
7585 codepoint +=
static_cast<int>((
static_cast<unsigned int>(current) - 0x57u) << factor);
7593 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7614 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7617 for (
auto range = ranges.begin(); range != ranges.end(); ++range)
7620 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
7626 error_message =
"invalid string: ill-formed UTF-8 byte";
7655 JSON_ASSERT(current ==
'\"');
7665 error_message =
"invalid string: missing closing quote";
7666 return token_type::parse_error;
7672 return token_type::value_string;
7716 const int codepoint1 = get_codepoint();
7717 int codepoint = codepoint1;
7719 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7721 error_message =
"invalid string: '\\u' must be followed by 4 hex digits";
7722 return token_type::parse_error;
7726 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7729 if (JSON_HEDLEY_LIKELY(get() ==
'\\' && get() ==
'u'))
7731 const int codepoint2 = get_codepoint();
7733 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7735 error_message =
"invalid string: '\\u' must be followed by 4 hex digits";
7736 return token_type::parse_error;
7740 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7743 codepoint =
static_cast<int>(
7745 (
static_cast<unsigned int>(codepoint1) << 10u)
7747 +
static_cast<unsigned int>(codepoint2)
7755 error_message =
"invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7756 return token_type::parse_error;
7761 error_message =
"invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7762 return token_type::parse_error;
7767 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7769 error_message =
"invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7770 return token_type::parse_error;
7775 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7778 if (codepoint < 0x80)
7781 add(
static_cast<char_int_type
>(codepoint));
7783 else if (codepoint <= 0x7FF)
7786 add(
static_cast<char_int_type
>(0xC0u | (
static_cast<unsigned int>(codepoint) >> 6u)));
7787 add(
static_cast<char_int_type
>(0x80u | (
static_cast<unsigned int>(codepoint) & 0x3Fu)));
7789 else if (codepoint <= 0xFFFF)
7792 add(
static_cast<char_int_type
>(0xE0u | (
static_cast<unsigned int>(codepoint) >> 12u)));
7793 add(
static_cast<char_int_type
>(0x80u | ((
static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7794 add(
static_cast<char_int_type
>(0x80u | (
static_cast<unsigned int>(codepoint) & 0x3Fu)));
7799 add(
static_cast<char_int_type
>(0xF0u | (
static_cast<unsigned int>(codepoint) >> 18u)));
7800 add(
static_cast<char_int_type
>(0x80u | ((
static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7801 add(
static_cast<char_int_type
>(0x80u | ((
static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7802 add(
static_cast<char_int_type
>(0x80u | (
static_cast<unsigned int>(codepoint) & 0x3Fu)));
7810 error_message =
"invalid string: forbidden character after backslash";
7811 return token_type::parse_error;
7820 error_message =
"invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7821 return token_type::parse_error;
7826 error_message =
"invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7827 return token_type::parse_error;
7832 error_message =
"invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7833 return token_type::parse_error;
7838 error_message =
"invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7839 return token_type::parse_error;
7844 error_message =
"invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7845 return token_type::parse_error;
7850 error_message =
"invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7851 return token_type::parse_error;
7856 error_message =
"invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7857 return token_type::parse_error;
7862 error_message =
"invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7863 return token_type::parse_error;
7868 error_message =
"invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7869 return token_type::parse_error;
7874 error_message =
"invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7875 return token_type::parse_error;
7880 error_message =
"invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7881 return token_type::parse_error;
7886 error_message =
"invalid string: control character U+000B (VT) must be escaped to \\u000B";
7887 return token_type::parse_error;
7892 error_message =
"invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7893 return token_type::parse_error;
7898 error_message =
"invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7899 return token_type::parse_error;
7904 error_message =
"invalid string: control character U+000E (SO) must be escaped to \\u000E";
7905 return token_type::parse_error;
7910 error_message =
"invalid string: control character U+000F (SI) must be escaped to \\u000F";
7911 return token_type::parse_error;
7916 error_message =
"invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7917 return token_type::parse_error;
7922 error_message =
"invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7923 return token_type::parse_error;
7928 error_message =
"invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7929 return token_type::parse_error;
7934 error_message =
"invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7935 return token_type::parse_error;
7940 error_message =
"invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7941 return token_type::parse_error;
7946 error_message =
"invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7947 return token_type::parse_error;
7952 error_message =
"invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7953 return token_type::parse_error;
7958 error_message =
"invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7959 return token_type::parse_error;
7964 error_message =
"invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7965 return token_type::parse_error;
7970 error_message =
"invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7971 return token_type::parse_error;
7976 error_message =
"invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7977 return token_type::parse_error;
7982 error_message =
"invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7983 return token_type::parse_error;
7988 error_message =
"invalid string: control character U+001C (FS) must be escaped to \\u001C";
7989 return token_type::parse_error;
7994 error_message =
"invalid string: control character U+001D (GS) must be escaped to \\u001D";
7995 return token_type::parse_error;
8000 error_message =
"invalid string: control character U+001E (RS) must be escaped to \\u001E";
8001 return token_type::parse_error;
8006 error_message =
"invalid string: control character U+001F (US) must be escaped to \\u001F";
8007 return token_type::parse_error;
8142 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8144 return token_type::parse_error;
8152 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8154 return token_type::parse_error;
8176 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8178 return token_type::parse_error;
8186 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8188 return token_type::parse_error;
8196 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8198 return token_type::parse_error;
8208 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8210 return token_type::parse_error;
8218 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8220 return token_type::parse_error;
8228 error_message =
"invalid string: ill-formed UTF-8 byte";
8229 return token_type::parse_error;
8272 error_message =
"invalid comment; missing closing '*/'";
8300 error_message =
"invalid comment; expecting '/' or '*' after '/'";
8306 JSON_HEDLEY_NON_NULL(2)
8307 static
void strtof(
float& f, const
char* str,
char** endptr) noexcept
8309 f = std::strtof(str, endptr);
8312 JSON_HEDLEY_NON_NULL(2)
8313 static
void strtof(
double& f, const
char* str,
char** endptr) noexcept
8315 f = std::strtod(str, endptr);
8318 JSON_HEDLEY_NON_NULL(2)
8319 static
void strtof(
long double& f, const
char* str,
char** endptr) noexcept
8321 f = std::strtold(str, endptr);
8371 token_type number_type = token_type::value_unsigned;
8379 goto scan_number_minus;
8385 goto scan_number_zero;
8399 goto scan_number_any1;
8409 number_type = token_type::value_integer;
8415 goto scan_number_zero;
8429 goto scan_number_any1;
8434 error_message =
"invalid number; expected digit after '-'";
8435 return token_type::parse_error;
8445 add(decimal_point_char);
8446 goto scan_number_decimal1;
8453 goto scan_number_exponent;
8457 goto scan_number_done;
8476 goto scan_number_any1;
8481 add(decimal_point_char);
8482 goto scan_number_decimal1;
8489 goto scan_number_exponent;
8493 goto scan_number_done;
8496scan_number_decimal1:
8498 number_type = token_type::value_float;
8513 goto scan_number_decimal2;
8518 error_message =
"invalid number; expected digit after '.'";
8519 return token_type::parse_error;
8523scan_number_decimal2:
8539 goto scan_number_decimal2;
8546 goto scan_number_exponent;
8550 goto scan_number_done;
8553scan_number_exponent:
8555 number_type = token_type::value_float;
8562 goto scan_number_sign;
8577 goto scan_number_any2;
8583 "invalid number; expected '+', '-', or digit after exponent";
8584 return token_type::parse_error;
8604 goto scan_number_any2;
8609 error_message =
"invalid number; expected digit after exponent sign";
8610 return token_type::parse_error;
8630 goto scan_number_any2;
8634 goto scan_number_done;
8642 char* endptr =
nullptr;
8646 if (number_type == token_type::value_unsigned)
8648 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8651 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8655 value_unsigned =
static_cast<number_unsigned_t
>(x);
8656 if (value_unsigned == x)
8658 return token_type::value_unsigned;
8662 else if (number_type == token_type::value_integer)
8664 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8667 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8671 value_integer =
static_cast<number_integer_t
>(x);
8672 if (value_integer == x)
8674 return token_type::value_integer;
8681 strtof(value_float, token_buffer.data(), &endptr);
8684 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8686 return token_type::value_float;
8694 JSON_HEDLEY_NON_NULL(2)
8695 token_type scan_literal(const char_type* literal_text, const std::
size_t length,
8696 token_type return_type)
8699 for (std::size_t i = 1; i < length; ++i)
8703 error_message =
"invalid literal";
8704 return token_type::parse_error;
8717 token_buffer.clear();
8718 token_string.clear();
8734 ++position.chars_read_total;
8735 ++position.chars_read_current_line;
8744 current = ia.get_character();
8747 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8749 token_string.push_back(char_traits<char_type>::to_char_type(current));
8752 if (current ==
'\n')
8754 ++position.lines_read;
8755 position.chars_read_current_line = 0;
8773 --position.chars_read_total;
8776 if (position.chars_read_current_line == 0)
8778 if (position.lines_read > 0)
8780 --position.lines_read;
8785 --position.chars_read_current_line;
8790 JSON_ASSERT(!token_string.empty());
8791 token_string.pop_back();
8798 token_buffer.push_back(
static_cast<typename string_t::value_type
>(c));
8809 return value_integer;
8815 return value_unsigned;
8827 return token_buffer;
8847 for (
const auto c : token_string)
8849 if (
static_cast<unsigned char>(c) <=
'\x1F')
8852 std::array<char, 9> cs{{}};
8853 static_cast<void>((std::snprintf)(cs.data(), cs.size(),
"<U+%.4X>",
static_cast<unsigned char>(c)));
8854 result += cs.data();
8859 result.push_back(
static_cast<std::string::value_type
>(c));
8867 JSON_HEDLEY_RETURNS_NON_NULL
8870 return error_message;
8886 return get() == 0xBB && get() == 0xBF;
8895 void skip_whitespace()
8901 while (current ==
' ' || current ==
'\t' || current ==
'\n' || current ==
'\r');
8907 if (position.chars_read_total == 0 && !skip_bom())
8909 error_message =
"invalid BOM; must be 0xEF 0xBB 0xBF if given";
8910 return token_type::parse_error;
8917 while (ignore_comments && current ==
'/')
8919 if (!scan_comment())
8921 return token_type::parse_error;
8932 return token_type::begin_array;
8934 return token_type::end_array;
8936 return token_type::begin_object;
8938 return token_type::end_object;
8940 return token_type::name_separator;
8942 return token_type::value_separator;
8947 std::array<char_type, 4> true_literal = {{
static_cast<char_type
>(
't'),
static_cast<char_type
>(
'r'),
static_cast<char_type
>(
'u'),
static_cast<char_type
>(
'e')}};
8948 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8952 std::array<char_type, 5> false_literal = {{
static_cast<char_type
>(
'f'),
static_cast<char_type
>(
'a'),
static_cast<char_type
>(
'l'),
static_cast<char_type
>(
's'),
static_cast<char_type
>(
'e')}};
8953 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8957 std::array<char_type, 4> null_literal = {{
static_cast<char_type
>(
'n'),
static_cast<char_type
>(
'u'),
static_cast<char_type
>(
'l'),
static_cast<char_type
>(
'l')}};
8958 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8963 return scan_string();
8977 return scan_number();
8982 case char_traits<char_type>::eof():
8983 return token_type::end_of_input;
8987 error_message =
"invalid literal";
8988 return token_type::parse_error;
8997 const bool ignore_comments =
false;
9003 bool next_unget =
false;
9009 std::vector<char_type> token_string {};
9012 string_t token_buffer {};
9015 const char* error_message =
"";
9018 number_integer_t value_integer = 0;
9019 number_unsigned_t value_unsigned = 0;
9020 number_float_t value_float = 0;
9023 const char_int_type decimal_point_char =
'.';
9027NLOHMANN_JSON_NAMESPACE_END
9053NLOHMANN_JSON_NAMESPACE_BEGIN
9058using null_function_t =
decltype(std::declval<T&>().null());
9061using boolean_function_t =
9062 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9064template<
typename T,
typename Integer>
9065using number_integer_function_t =
9066 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9068template<
typename T,
typename Un
signed>
9069using number_unsigned_function_t =
9070 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9072template<
typename T,
typename Float,
typename String>
9073using number_float_function_t =
decltype(std::declval<T&>().number_float(
9074 std::declval<Float>(), std::declval<const String&>()));
9076template<
typename T,
typename String>
9077using string_function_t =
9078 decltype(std::declval<T&>().string(std::declval<String&>()));
9080template<
typename T,
typename Binary>
9081using binary_function_t =
9082 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9085using start_object_function_t =
9086 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9088template<
typename T,
typename String>
9089using key_function_t =
9090 decltype(std::declval<T&>().key(std::declval<String&>()));
9093using end_object_function_t =
decltype(std::declval<T&>().end_object());
9096using start_array_function_t =
9097 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9100using end_array_function_t =
decltype(std::declval<T&>().end_array());
9102template<
typename T,
typename Exception>
9103using parse_error_function_t =
decltype(std::declval<T&>().parse_error(
9104 std::declval<std::size_t>(), std::declval<const std::string&>(),
9105 std::declval<const Exception&>()));
9107template<
typename SAX,
typename BasicJsonType>
9112 "BasicJsonType must be of type basic_json<...>");
9114 using number_integer_t =
typename BasicJsonType::number_integer_t;
9115 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
9116 using number_float_t =
typename BasicJsonType::number_float_t;
9117 using string_t =
typename BasicJsonType::string_t;
9118 using binary_t =
typename BasicJsonType::binary_t;
9119 using exception_t =
typename BasicJsonType::exception;
9122 static constexpr bool value =
9123 is_detected_exact<bool, null_function_t, SAX>::value &&
9124 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9125 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9126 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9127 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9128 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9129 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9130 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9131 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9132 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9133 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9134 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9135 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9138template<
typename SAX,
typename BasicJsonType>
9143 "BasicJsonType must be of type basic_json<...>");
9145 using number_integer_t =
typename BasicJsonType::number_integer_t;
9146 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
9147 using number_float_t =
typename BasicJsonType::number_float_t;
9148 using string_t =
typename BasicJsonType::string_t;
9149 using binary_t =
typename BasicJsonType::binary_t;
9150 using exception_t =
typename BasicJsonType::exception;
9153 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9154 "Missing/invalid function: bool null()");
9155 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9156 "Missing/invalid function: bool boolean(bool)");
9157 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9158 "Missing/invalid function: bool boolean(bool)");
9160 is_detected_exact<bool, number_integer_function_t, SAX,
9161 number_integer_t>::value,
9162 "Missing/invalid function: bool number_integer(number_integer_t)");
9164 is_detected_exact<bool, number_unsigned_function_t, SAX,
9165 number_unsigned_t>::value,
9166 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9167 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9168 number_float_t, string_t>::value,
9169 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9171 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9172 "Missing/invalid function: bool string(string_t&)");
9174 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9175 "Missing/invalid function: bool binary(binary_t&)");
9176 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9177 "Missing/invalid function: bool start_object(std::size_t)");
9178 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9179 "Missing/invalid function: bool key(string_t&)");
9180 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9181 "Missing/invalid function: bool end_object()");
9182 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9183 "Missing/invalid function: bool start_array(std::size_t)");
9184 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9185 "Missing/invalid function: bool end_array()");
9187 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9188 "Missing/invalid function: bool parse_error(std::size_t, const "
9189 "std::string&, const exception&)");
9193NLOHMANN_JSON_NAMESPACE_END
9202NLOHMANN_JSON_NAMESPACE_BEGIN
9223 return *
reinterpret_cast<char*
>(&num) == 1;
9233template<
typename BasicJsonType,
typename InputAdapterType,
typename SAX = json_sax_dom_parser<BasicJsonType>>
9236 using number_integer_t =
typename BasicJsonType::number_integer_t;
9237 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
9238 using number_float_t =
typename BasicJsonType::number_float_t;
9239 using string_t =
typename BasicJsonType::string_t;
9240 using binary_t =
typename BasicJsonType::binary_t;
9241 using json_sax_t = SAX;
9242 using char_type =
typename InputAdapterType::char_type;
9251 explicit binary_reader(InputAdapterType&& adapter,
const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9271 JSON_HEDLEY_NON_NULL(3)
9274 const
bool strict = true,
9278 bool result =
false;
9282 case input_format_t::bson:
9283 result = parse_bson_internal();
9286 case input_format_t::cbor:
9287 result = parse_cbor_internal(
true, tag_handler);
9290 case input_format_t::msgpack:
9291 result = parse_msgpack_internal();
9294 case input_format_t::ubjson:
9295 case input_format_t::bjdata:
9296 result = parse_ubjson_internal();
9299 case input_format_t::json:
9307 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9318 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9319 exception_message(input_format, concat(
"expected end of input; last byte: 0x", get_token_string()),
"value"),
nullptr));
9337 std::int32_t document_size{};
9338 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9340 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(
static_cast<std::size_t
>(-1))))
9345 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(
false)))
9350 return sax->end_object();
9362 auto out = std::back_inserter(result);
9366 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson,
"cstring")))
9370 if (current == 0x00)
9374 *out++ =
static_cast<typename string_t::value_type
>(current);
9389 template<
typename NumberType>
9392 if (JSON_HEDLEY_UNLIKELY(len < 1))
9394 auto last_token = get_token_string();
9395 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9396 exception_message(input_format_t::bson, concat(
"string length must be at least 1, is ", std::to_string(len)),
"string"),
nullptr));
9411 template<
typename NumberType>
9414 if (JSON_HEDLEY_UNLIKELY(len < 0))
9416 auto last_token = get_token_string();
9417 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9418 exception_message(input_format_t::bson, concat(
"byte array length cannot be negative, is ", std::to_string(len)),
"binary"),
nullptr));
9422 std::uint8_t subtype{};
9423 get_number<std::uint8_t>(input_format_t::bson, subtype);
9424 result.set_subtype(subtype);
9426 return get_binary(input_format_t::bson, len, result);
9440 const std::size_t element_type_parse_position)
9442 switch (element_type)
9447 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
9454 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len,
value) && sax->string(
value);
9459 return parse_bson_internal();
9464 return parse_bson_array();
9471 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len,
value) && sax->binary(
value);
9476 return sax->boolean(get() != 0);
9486 std::int32_t
value{};
9487 return get_number<std::int32_t, true>(input_format_t::bson,
value) && sax->number_integer(
value);
9492 std::int64_t
value{};
9493 return get_number<std::int64_t, true>(input_format_t::bson,
value) && sax->number_integer(
value);
9498 std::array<char, 3> cr{{}};
9499 static_cast<void>((std::snprintf)(cr.data(), cr.size(),
"%.2hhX",
static_cast<unsigned char>(element_type)));
9500 const std::string cr_str{cr.data()};
9501 return sax->parse_error(element_type_parse_position, cr_str,
9502 parse_error::create(114, element_type_parse_position, concat(
"Unsupported BSON record type 0x", cr_str),
nullptr));
9523 while (
auto element_type = get())
9525 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson,
"element list")))
9530 const std::size_t element_type_parse_position = chars_read;
9531 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(
key)))
9536 if (!is_array && !sax->key(
key))
9541 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9559 std::int32_t document_size{};
9560 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9562 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(
static_cast<std::size_t
>(-1))))
9567 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(
true)))
9572 return sax->end_array();
9590 switch (get_char ? get() : current)
9594 return unexpect_eof(input_format_t::cbor,
"value");
9621 return sax->number_unsigned(
static_cast<number_unsigned_t
>(current));
9625 std::uint8_t number{};
9626 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9631 std::uint16_t number{};
9632 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9637 std::uint32_t number{};
9638 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9643 std::uint64_t number{};
9644 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9672 return sax->number_integer(
static_cast<std::int8_t
>(0x20 - 1 - current));
9676 std::uint8_t number{};
9677 return get_number(input_format_t::cbor, number) && sax->number_integer(
static_cast<number_integer_t
>(-1) - number);
9682 std::uint16_t number{};
9683 return get_number(input_format_t::cbor, number) && sax->number_integer(
static_cast<number_integer_t
>(-1) - number);
9688 std::uint32_t number{};
9689 return get_number(input_format_t::cbor, number) && sax->number_integer(
static_cast<number_integer_t
>(-1) - number);
9694 std::uint64_t number{};
9695 return get_number(input_format_t::cbor, number) && sax->number_integer(
static_cast<number_integer_t
>(-1)
9696 -
static_cast<number_integer_t
>(number));
9731 return get_cbor_binary(b) && sax->binary(b);
9766 return get_cbor_string(s) && sax->string(s);
9794 return get_cbor_array(
9795 conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9800 return get_number(input_format_t::cbor, len) && get_cbor_array(
static_cast<std::size_t
>(len), tag_handler);
9805 std::uint16_t len{};
9806 return get_number(input_format_t::cbor, len) && get_cbor_array(
static_cast<std::size_t
>(len), tag_handler);
9811 std::uint32_t len{};
9812 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9817 std::uint64_t len{};
9818 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9822 return get_cbor_array(
static_cast<std::size_t
>(-1), tag_handler);
9849 return get_cbor_object(conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9854 return get_number(input_format_t::cbor, len) && get_cbor_object(
static_cast<std::size_t
>(len), tag_handler);
9859 std::uint16_t len{};
9860 return get_number(input_format_t::cbor, len) && get_cbor_object(
static_cast<std::size_t
>(len), tag_handler);
9865 std::uint32_t len{};
9866 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9871 std::uint64_t len{};
9872 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9876 return get_cbor_object(
static_cast<std::size_t
>(-1), tag_handler);
9898 switch (tag_handler)
9900 case cbor_tag_handler_t::error:
9902 auto last_token = get_token_string();
9903 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9904 exception_message(input_format_t::cbor, concat(
"invalid byte: 0x", last_token),
"value"),
nullptr));
9907 case cbor_tag_handler_t::ignore:
9914 std::uint8_t subtype_to_ignore{};
9915 get_number(input_format_t::cbor, subtype_to_ignore);
9920 std::uint16_t subtype_to_ignore{};
9921 get_number(input_format_t::cbor, subtype_to_ignore);
9926 std::uint32_t subtype_to_ignore{};
9927 get_number(input_format_t::cbor, subtype_to_ignore);
9932 std::uint64_t subtype_to_ignore{};
9933 get_number(input_format_t::cbor, subtype_to_ignore);
9939 return parse_cbor_internal(
true, tag_handler);
9942 case cbor_tag_handler_t::store:
9950 std::uint8_t subtype{};
9951 get_number(input_format_t::cbor, subtype);
9952 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9957 std::uint16_t subtype{};
9958 get_number(input_format_t::cbor, subtype);
9959 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9964 std::uint32_t subtype{};
9965 get_number(input_format_t::cbor, subtype);
9966 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9971 std::uint64_t subtype{};
9972 get_number(input_format_t::cbor, subtype);
9973 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9977 return parse_cbor_internal(
true, tag_handler);
9980 return get_cbor_binary(b) && sax->binary(b);
9990 return sax->boolean(
false);
9993 return sax->boolean(
true);
10000 const auto byte1_raw = get();
10001 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"number")))
10005 const auto byte2_raw = get();
10006 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"number")))
10011 const auto byte1 =
static_cast<unsigned char>(byte1_raw);
10012 const auto byte2 =
static_cast<unsigned char>(byte2_raw);
10022 const auto half =
static_cast<unsigned int>((byte1 << 8u) + byte2);
10023 const double val = [&half]
10025 const int exp = (half >> 10u) & 0x1Fu;
10026 const unsigned int mant = half & 0x3FFu;
10027 JSON_ASSERT(0 <= exp&& exp <= 32);
10028 JSON_ASSERT(mant <= 1024);
10032 return std::ldexp(mant, -24);
10035 ? std::numeric_limits<double>::infinity()
10036 : std::numeric_limits<double>::quiet_NaN();
10038 return std::ldexp(mant + 1024, exp - 25);
10041 return sax->number_float((half & 0x8000u) != 0
10042 ?
static_cast<number_float_t
>(-val)
10043 :
static_cast<number_float_t
>(val),
"");
10049 return get_number(input_format_t::cbor, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10055 return get_number(input_format_t::cbor, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10060 auto last_token = get_token_string();
10061 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10062 exception_message(input_format_t::cbor, concat(
"invalid byte: 0x", last_token),
"value"),
nullptr));
10080 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"string")))
10113 return get_string(input_format_t::cbor,
static_cast<unsigned int>(current) & 0x1Fu, result);
10118 std::uint8_t len{};
10119 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10124 std::uint16_t len{};
10125 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10130 std::uint32_t len{};
10131 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10136 std::uint64_t len{};
10137 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10142 while (get() != 0xFF)
10145 if (!get_cbor_string(chunk))
10149 result.append(chunk);
10156 auto last_token = get_token_string();
10157 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10158 exception_message(input_format_t::cbor, concat(
"expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token),
"string"),
nullptr));
10176 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor,
"binary")))
10209 return get_binary(input_format_t::cbor,
static_cast<unsigned int>(current) & 0x1Fu, result);
10214 std::uint8_t len{};
10215 return get_number(input_format_t::cbor, len) &&
10216 get_binary(input_format_t::cbor, len, result);
10221 std::uint16_t len{};
10222 return get_number(input_format_t::cbor, len) &&
10223 get_binary(input_format_t::cbor, len, result);
10228 std::uint32_t len{};
10229 return get_number(input_format_t::cbor, len) &&
10230 get_binary(input_format_t::cbor, len, result);
10235 std::uint64_t len{};
10236 return get_number(input_format_t::cbor, len) &&
10237 get_binary(input_format_t::cbor, len, result);
10242 while (get() != 0xFF)
10245 if (!get_cbor_binary(chunk))
10249 result.insert(result.end(), chunk.begin(), chunk.end());
10256 auto last_token = get_token_string();
10257 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10258 exception_message(input_format_t::cbor, concat(
"expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token),
"binary"),
nullptr));
10272 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10277 if (len !=
static_cast<std::size_t
>(-1))
10279 for (std::size_t i = 0; i < len; ++i)
10281 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler)))
10289 while (get() != 0xFF)
10291 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
false, tag_handler)))
10298 return sax->end_array();
10310 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10318 if (len !=
static_cast<std::size_t
>(-1))
10320 for (std::size_t i = 0; i < len; ++i)
10323 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(
key) || !sax->key(
key)))
10328 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler)))
10337 while (get() != 0xFF)
10339 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(
key) || !sax->key(
key)))
10344 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(
true, tag_handler)))
10353 return sax->end_object();
10369 return unexpect_eof(input_format_t::msgpack,
"value");
10500 return sax->number_unsigned(
static_cast<number_unsigned_t
>(current));
10519 return get_msgpack_object(conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x0Fu));
10538 return get_msgpack_array(conditional_static_cast<std::size_t>(
static_cast<unsigned int>(current) & 0x0Fu));
10578 return get_msgpack_string(s) && sax->string(s);
10582 return sax->null();
10585 return sax->boolean(
false);
10588 return sax->boolean(
true);
10603 return get_msgpack_binary(b) && sax->binary(b);
10609 return get_number(input_format_t::msgpack, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10615 return get_number(input_format_t::msgpack, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
10620 std::uint8_t number{};
10621 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10626 std::uint16_t number{};
10627 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10632 std::uint32_t number{};
10633 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10638 std::uint64_t number{};
10639 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10644 std::int8_t number{};
10645 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10650 std::int16_t number{};
10651 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10656 std::int32_t number{};
10657 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10662 std::int64_t number{};
10663 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10668 std::uint16_t len{};
10669 return get_number(input_format_t::msgpack, len) && get_msgpack_array(
static_cast<std::size_t
>(len));
10674 std::uint32_t len{};
10675 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10680 std::uint16_t len{};
10681 return get_number(input_format_t::msgpack, len) && get_msgpack_object(
static_cast<std::size_t
>(len));
10686 std::uint32_t len{};
10687 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10723 return sax->number_integer(
static_cast<std::int8_t
>(current));
10727 auto last_token = get_token_string();
10728 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10729 exception_message(input_format_t::msgpack, concat(
"invalid byte: 0x", last_token),
"value"),
nullptr));
10746 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack,
"string")))
10787 return get_string(input_format_t::msgpack,
static_cast<unsigned int>(current) & 0x1Fu, result);
10792 std::uint8_t len{};
10793 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10798 std::uint16_t len{};
10799 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10804 std::uint32_t len{};
10805 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10810 auto last_token = get_token_string();
10811 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10812 exception_message(input_format_t::msgpack, concat(
"expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token),
"string"),
nullptr));
10830 auto assign_and_return_true = [&result](std::int8_t subtype)
10832 result.set_subtype(
static_cast<std::uint8_t
>(subtype));
10840 std::uint8_t len{};
10841 return get_number(input_format_t::msgpack, len) &&
10842 get_binary(input_format_t::msgpack, len, result);
10847 std::uint16_t len{};
10848 return get_number(input_format_t::msgpack, len) &&
10849 get_binary(input_format_t::msgpack, len, result);
10854 std::uint32_t len{};
10855 return get_number(input_format_t::msgpack, len) &&
10856 get_binary(input_format_t::msgpack, len, result);
10861 std::uint8_t len{};
10862 std::int8_t subtype{};
10863 return get_number(input_format_t::msgpack, len) &&
10864 get_number(input_format_t::msgpack, subtype) &&
10865 get_binary(input_format_t::msgpack, len, result) &&
10866 assign_and_return_true(subtype);
10871 std::uint16_t len{};
10872 std::int8_t subtype{};
10873 return get_number(input_format_t::msgpack, len) &&
10874 get_number(input_format_t::msgpack, subtype) &&
10875 get_binary(input_format_t::msgpack, len, result) &&
10876 assign_and_return_true(subtype);
10881 std::uint32_t len{};
10882 std::int8_t subtype{};
10883 return get_number(input_format_t::msgpack, len) &&
10884 get_number(input_format_t::msgpack, subtype) &&
10885 get_binary(input_format_t::msgpack, len, result) &&
10886 assign_and_return_true(subtype);
10891 std::int8_t subtype{};
10892 return get_number(input_format_t::msgpack, subtype) &&
10893 get_binary(input_format_t::msgpack, 1, result) &&
10894 assign_and_return_true(subtype);
10899 std::int8_t subtype{};
10900 return get_number(input_format_t::msgpack, subtype) &&
10901 get_binary(input_format_t::msgpack, 2, result) &&
10902 assign_and_return_true(subtype);
10907 std::int8_t subtype{};
10908 return get_number(input_format_t::msgpack, subtype) &&
10909 get_binary(input_format_t::msgpack, 4, result) &&
10910 assign_and_return_true(subtype);
10915 std::int8_t subtype{};
10916 return get_number(input_format_t::msgpack, subtype) &&
10917 get_binary(input_format_t::msgpack, 8, result) &&
10918 assign_and_return_true(subtype);
10923 std::int8_t subtype{};
10924 return get_number(input_format_t::msgpack, subtype) &&
10925 get_binary(input_format_t::msgpack, 16, result) &&
10926 assign_and_return_true(subtype);
10940 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10945 for (std::size_t i = 0; i < len; ++i)
10947 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10953 return sax->end_array();
10962 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10968 for (std::size_t i = 0; i < len; ++i)
10971 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(
key) || !sax->key(
key)))
10976 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10983 return sax->end_object();
10999 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11023 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"value")))
11032 std::uint8_t len{};
11033 return get_number(input_format, len) && get_string(input_format, len, result);
11039 return get_number(input_format, len) && get_string(input_format, len, result);
11044 std::int16_t len{};
11045 return get_number(input_format, len) && get_string(input_format, len, result);
11050 std::int32_t len{};
11051 return get_number(input_format, len) && get_string(input_format, len, result);
11056 std::int64_t len{};
11057 return get_number(input_format, len) && get_string(input_format, len, result);
11062 if (input_format != input_format_t::bjdata)
11066 std::uint16_t len{};
11067 return get_number(input_format, len) && get_string(input_format, len, result);
11072 if (input_format != input_format_t::bjdata)
11076 std::uint32_t len{};
11077 return get_number(input_format, len) && get_string(input_format, len, result);
11082 if (input_format != input_format_t::bjdata)
11086 std::uint64_t len{};
11087 return get_number(input_format, len) && get_string(input_format, len, result);
11093 auto last_token = get_token_string();
11094 std::string message;
11096 if (input_format != input_format_t::bjdata)
11098 message =
"expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11102 message =
"expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11104 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message,
"string"),
nullptr));
11113 std::pair<std::size_t, char_int_type> size_and_type;
11115 bool no_ndarray =
true;
11117 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11122 if (size_and_type.first != npos)
11124 if (size_and_type.second != 0)
11126 if (size_and_type.second !=
'N')
11128 for (std::size_t i = 0; i < size_and_type.first; ++i)
11130 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11134 dim.push_back(dimlen);
11140 for (std::size_t i = 0; i < size_and_type.first; ++i)
11142 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11146 dim.push_back(dimlen);
11152 while (current !=
']')
11154 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11158 dim.push_back(dimlen);
11180 prefix = get_ignore_noop();
11187 std::uint8_t number{};
11188 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11192 result =
static_cast<std::size_t
>(number);
11198 std::int8_t number{};
11199 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11205 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11206 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11208 result =
static_cast<std::size_t
>(number);
11214 std::int16_t number{};
11215 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11221 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11222 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11224 result =
static_cast<std::size_t
>(number);
11230 std::int32_t number{};
11231 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11237 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11238 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11240 result =
static_cast<std::size_t
>(number);
11246 std::int64_t number{};
11247 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11253 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11254 exception_message(input_format,
"count in an optimized container must be positive",
"size"),
nullptr));
11256 if (!value_in_range_of<std::size_t>(number))
11258 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11259 exception_message(input_format,
"integer value overflow",
"size"),
nullptr));
11261 result =
static_cast<std::size_t
>(number);
11267 if (input_format != input_format_t::bjdata)
11271 std::uint16_t number{};
11272 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11276 result =
static_cast<std::size_t
>(number);
11282 if (input_format != input_format_t::bjdata)
11286 std::uint32_t number{};
11287 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11291 result = conditional_static_cast<std::size_t>(number);
11297 if (input_format != input_format_t::bjdata)
11301 std::uint64_t number{};
11302 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11306 if (!value_in_range_of<std::size_t>(number))
11308 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11309 exception_message(input_format,
"integer value overflow",
"size"),
nullptr));
11311 result = detail::conditional_static_cast<std::size_t>(number);
11317 if (input_format != input_format_t::bjdata)
11323 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format,
"ndarray dimensional vector is not allowed",
"size"),
nullptr));
11325 std::vector<size_t> dim;
11326 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11330 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1))
11332 result = dim.at(dim.size() - 1);
11346 string_t
key =
"_ArraySize_";
11347 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(
key) || !sax->start_array(dim.size())))
11355 if (result == 0 || result == npos)
11357 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format,
"excessive ndarray size caused overflow",
"size"),
nullptr));
11359 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(
static_cast<number_unsigned_t
>(i))))
11365 return sax->end_array();
11374 auto last_token = get_token_string();
11375 std::string message;
11377 if (input_format != input_format_t::bjdata)
11379 message =
"expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11383 message =
"expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11385 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message,
"size"),
nullptr));
11401 result.first = npos;
11403 bool is_ndarray =
false;
11407 if (current ==
'$')
11409 result.second = get();
11410 if (input_format == input_format_t::bjdata
11411 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11413 auto last_token = get_token_string();
11414 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11415 exception_message(input_format, concat(
"marker 0x", last_token,
" is not a permitted optimized array type"),
"type"),
nullptr));
11418 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"type")))
11424 if (JSON_HEDLEY_UNLIKELY(current !=
'#'))
11426 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"value")))
11430 auto last_token = get_token_string();
11431 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11432 exception_message(input_format, concat(
"expected '#' after type information; last byte: 0x", last_token),
"size"),
nullptr));
11435 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11436 if (input_format == input_format_t::bjdata && is_ndarray)
11438 if (inside_ndarray)
11440 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11441 exception_message(input_format,
"ndarray can not be recursive",
"size"),
nullptr));
11443 result.second |= (1 << 8);
11448 if (current ==
'#')
11450 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11451 if (input_format == input_format_t::bjdata && is_ndarray)
11453 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11454 exception_message(input_format,
"ndarray requires both type and size",
"size"),
nullptr));
11471 return unexpect_eof(input_format,
"value");
11474 return sax->boolean(
true);
11476 return sax->boolean(
false);
11479 return sax->null();
11483 std::uint8_t number{};
11484 return get_number(input_format, number) && sax->number_unsigned(number);
11489 std::int8_t number{};
11490 return get_number(input_format, number) && sax->number_integer(number);
11495 std::int16_t number{};
11496 return get_number(input_format, number) && sax->number_integer(number);
11501 std::int32_t number{};
11502 return get_number(input_format, number) && sax->number_integer(number);
11507 std::int64_t number{};
11508 return get_number(input_format, number) && sax->number_integer(number);
11513 if (input_format != input_format_t::bjdata)
11517 std::uint16_t number{};
11518 return get_number(input_format, number) && sax->number_unsigned(number);
11523 if (input_format != input_format_t::bjdata)
11527 std::uint32_t number{};
11528 return get_number(input_format, number) && sax->number_unsigned(number);
11533 if (input_format != input_format_t::bjdata)
11537 std::uint64_t number{};
11538 return get_number(input_format, number) && sax->number_unsigned(number);
11543 if (input_format != input_format_t::bjdata)
11547 const auto byte1_raw = get();
11548 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"number")))
11552 const auto byte2_raw = get();
11553 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"number")))
11558 const auto byte1 =
static_cast<unsigned char>(byte1_raw);
11559 const auto byte2 =
static_cast<unsigned char>(byte2_raw);
11569 const auto half =
static_cast<unsigned int>((byte2 << 8u) + byte1);
11570 const double val = [&half]
11572 const int exp = (half >> 10u) & 0x1Fu;
11573 const unsigned int mant = half & 0x3FFu;
11574 JSON_ASSERT(0 <= exp&& exp <= 32);
11575 JSON_ASSERT(mant <= 1024);
11579 return std::ldexp(mant, -24);
11582 ? std::numeric_limits<double>::infinity()
11583 : std::numeric_limits<double>::quiet_NaN();
11585 return std::ldexp(mant + 1024, exp - 25);
11588 return sax->number_float((half & 0x8000u) != 0
11589 ?
static_cast<number_float_t
>(-val)
11590 :
static_cast<number_float_t
>(val),
"");
11596 return get_number(input_format, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
11602 return get_number(input_format, number) && sax->number_float(
static_cast<number_float_t
>(number),
"");
11607 return get_ubjson_high_precision_number();
11613 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"char")))
11617 if (JSON_HEDLEY_UNLIKELY(current > 127))
11619 auto last_token = get_token_string();
11620 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11621 exception_message(input_format, concat(
"byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token),
"char"),
nullptr));
11623 string_t s(1,
static_cast<typename string_t::value_type
>(current));
11624 return sax->string(s);
11630 return get_ubjson_string(s) && sax->string(s);
11634 return get_ubjson_array();
11637 return get_ubjson_object();
11642 auto last_token = get_token_string();
11643 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format,
"invalid byte: 0x" + last_token,
"value"),
nullptr));
11651 std::pair<std::size_t, char_int_type> size_and_type;
11652 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11660 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11662 size_and_type.second &= ~(
static_cast<char_int_type
>(1) << 8);
11663 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](
const bjd_type & p, char_int_type t)
11665 return p.first < t;
11667 string_t
key =
"_ArrayType_";
11668 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11670 auto last_token = get_token_string();
11671 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11672 exception_message(input_format,
"invalid byte: 0x" + last_token,
"type"),
nullptr));
11675 string_t type = it->second;
11676 if (JSON_HEDLEY_UNLIKELY(!sax->key(
key) || !sax->string(type)))
11681 if (size_and_type.second ==
'C')
11683 size_and_type.second =
'U';
11686 key =
"_ArrayData_";
11687 if (JSON_HEDLEY_UNLIKELY(!sax->key(
key) || !sax->start_array(size_and_type.first) ))
11692 for (std::size_t i = 0; i < size_and_type.first; ++i)
11694 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11700 return (sax->end_array() && sax->end_object());
11703 if (size_and_type.first != npos)
11705 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11710 if (size_and_type.second != 0)
11712 if (size_and_type.second !=
'N')
11714 for (std::size_t i = 0; i < size_and_type.first; ++i)
11716 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11725 for (std::size_t i = 0; i < size_and_type.first; ++i)
11727 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11736 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(
static_cast<std::size_t
>(-1))))
11741 while (current !=
']')
11743 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(
false)))
11751 return sax->end_array();
11759 std::pair<std::size_t, char_int_type> size_and_type;
11760 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11766 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11768 auto last_token = get_token_string();
11769 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11770 exception_message(input_format,
"BJData object does not support ND-array size in optimized format",
"object"),
nullptr));
11774 if (size_and_type.first != npos)
11776 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11781 if (size_and_type.second != 0)
11783 for (std::size_t i = 0; i < size_and_type.first; ++i)
11785 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(
key) || !sax->key(
key)))
11789 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11798 for (std::size_t i = 0; i < size_and_type.first; ++i)
11800 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(
key) || !sax->key(
key)))
11804 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11814 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(
static_cast<std::size_t
>(-1))))
11819 while (current !=
'}')
11821 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(
key,
false) || !sax->key(
key)))
11825 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11834 return sax->end_object();
11840 bool get_ubjson_high_precision_number()
11843 std::size_t size{};
11844 bool no_ndarray =
true;
11845 auto res = get_ubjson_size_value(size, no_ndarray);
11846 if (JSON_HEDLEY_UNLIKELY(!res))
11852 std::vector<char> number_vector;
11853 for (std::size_t i = 0; i < size; ++i)
11856 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format,
"number")))
11860 number_vector.push_back(
static_cast<char>(current));
11864 using ia_type =
decltype(detail::input_adapter(number_vector));
11866 const auto result_number = number_lexer.scan();
11867 const auto number_string = number_lexer.get_token_string();
11868 const auto result_remainder = number_lexer.scan();
11872 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11874 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11875 exception_message(input_format, concat(
"invalid number text: ", number_lexer.get_token_string()),
"high-precision number"),
nullptr));
11878 switch (result_number)
11880 case token_type::value_integer:
11881 return sax->number_integer(number_lexer.get_number_integer());
11882 case token_type::value_unsigned:
11883 return sax->number_unsigned(number_lexer.get_number_unsigned());
11884 case token_type::value_float:
11885 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11886 case token_type::uninitialized:
11887 case token_type::literal_true:
11888 case token_type::literal_false:
11889 case token_type::literal_null:
11890 case token_type::value_string:
11891 case token_type::begin_array:
11892 case token_type::begin_object:
11893 case token_type::end_array:
11894 case token_type::end_object:
11895 case token_type::name_separator:
11896 case token_type::value_separator:
11897 case token_type::parse_error:
11898 case token_type::end_of_input:
11899 case token_type::literal_or_value:
11901 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11902 exception_message(input_format, concat(
"invalid number text: ", number_lexer.get_token_string()),
"high-precision number"),
nullptr));
11922 return current = ia.get_character();
11934 while (current ==
'N');
11954 template<
typename NumberType,
bool InputIsLittleEndian = false>
11955 bool get_number(
const input_format_t format, NumberType& result)
11958 std::array<std::uint8_t,
sizeof(NumberType)> vec{};
11959 for (std::size_t i = 0; i <
sizeof(NumberType); ++i)
11962 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format,
"number")))
11968 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11970 vec[
sizeof(NumberType) - i - 1] =
static_cast<std::uint8_t
>(current);
11974 vec[i] =
static_cast<std::uint8_t
>(current);
11979 std::memcpy(&result, vec.data(),
sizeof(NumberType));
11997 template<
typename NumberType>
11999 const NumberType len,
12002 bool success =
true;
12003 for (NumberType i = 0; i < len; i++)
12006 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format,
"string")))
12011 result.push_back(
static_cast<typename string_t::value_type
>(current));
12030 template<
typename NumberType>
12032 const NumberType len,
12035 bool success =
true;
12036 for (NumberType i = 0; i < len; i++)
12039 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format,
"binary")))
12044 result.push_back(
static_cast<std::uint8_t
>(current));
12054 JSON_HEDLEY_NON_NULL(3)
12059 return sax->parse_error(chars_read,
"<end of file>",
12060 parse_error::create(110, chars_read, exception_message(format,
"unexpected end of input", context),
nullptr));
12070 std::array<char, 3> cr{{}};
12071 static_cast<void>((std::snprintf)(cr.data(), cr.size(),
"%.2hhX",
static_cast<unsigned char>(current)));
12072 return std::string{cr.data()};
12082 const std::string&
detail,
12083 const std::string& context)
const
12085 std::string error_msg =
"syntax error while parsing ";
12089 case input_format_t::cbor:
12090 error_msg +=
"CBOR";
12093 case input_format_t::msgpack:
12094 error_msg +=
"MessagePack";
12097 case input_format_t::ubjson:
12098 error_msg +=
"UBJSON";
12101 case input_format_t::bson:
12102 error_msg +=
"BSON";
12105 case input_format_t::bjdata:
12106 error_msg +=
"BJData";
12109 case input_format_t::json:
12111 JSON_ASSERT(
false);
12114 return concat(error_msg,
' ', context,
": ",
detail);
12118 static JSON_INLINE_VARIABLE
constexpr std::size_t npos =
static_cast<std::size_t
>(-1);
12127 std::size_t chars_read = 0;
12136 json_sax_t* sax =
nullptr;
12139#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12140 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12142#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12143 make_array<bjd_type>( \
12144 bjd_type{'C', "char"}, \
12145 bjd_type{'D', "double"}, \
12146 bjd_type{'I', "int16"}, \
12147 bjd_type{'L', "int64"}, \
12148 bjd_type{'M', "uint64"}, \
12149 bjd_type{'U', "uint8"}, \
12150 bjd_type{'d', "single"}, \
12151 bjd_type{'i', "int8"}, \
12152 bjd_type{'l', "int32"}, \
12153 bjd_type{'m', "uint32"}, \
12154 bjd_type{'u', "uint16"})
12156 JSON_PRIVATE_UNLESS_TESTED:
12159 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12160 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12162 using bjd_type = std::pair<char_int_type, string_t>;
12164 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12165 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12167#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12168#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12171#ifndef JSON_HAS_CPP_17
12172 template<
typename BasicJsonType,
typename InputAdapterType,
typename SAX>
12177NLOHMANN_JSON_NAMESPACE_END
12196#include <functional>
12218NLOHMANN_JSON_NAMESPACE_BEGIN
12241template<
typename BasicJsonType>
12242using parser_callback_t =
12243 std::function<bool(
int , parse_event_t , BasicJsonType& )>;
12250template<
typename BasicJsonType,
typename InputAdapterType>
12253 using number_integer_t =
typename BasicJsonType::number_integer_t;
12254 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
12255 using number_float_t =
typename BasicJsonType::number_float_t;
12256 using string_t =
typename BasicJsonType::string_t;
12258 using token_type =
typename lexer_t::token_type;
12263 const parser_callback_t<BasicJsonType> cb =
nullptr,
12264 const bool allow_exceptions_ =
true,
12265 const bool skip_comments =
false)
12267 , m_lexer(std::move(adapter), skip_comments)
12268 , allow_exceptions(allow_exceptions_)
12284 void parse(
const bool strict, BasicJsonType& result)
12289 sax_parse_internal(&sdp);
12292 if (
strict && (get_token() != token_type::end_of_input))
12294 sdp.parse_error(m_lexer.get_position(),
12295 m_lexer.get_token_string(),
12296 parse_error::create(101, m_lexer.get_position(),
12297 exception_message(token_type::end_of_input,
"value"),
nullptr));
12301 if (sdp.is_errored())
12303 result = value_t::discarded;
12309 if (result.is_discarded())
12317 sax_parse_internal(&sdp);
12320 if (
strict && (get_token() != token_type::end_of_input))
12322 sdp.parse_error(m_lexer.get_position(),
12323 m_lexer.get_token_string(),
12324 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input,
"value"),
nullptr));
12328 if (sdp.is_errored())
12330 result = value_t::discarded;
12335 result.assert_invariant();
12347 return sax_parse(&sax_acceptor,
strict);
12350 template<
typename SAX>
12351 JSON_HEDLEY_NON_NULL(2)
12352 bool sax_parse(SAX* sax, const
bool strict = true)
12355 const bool result = sax_parse_internal(sax);
12358 if (result && strict && (get_token() != token_type::end_of_input))
12360 return sax->parse_error(m_lexer.get_position(),
12361 m_lexer.get_token_string(),
12362 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input,
"value"),
nullptr));
12369 template<
typename SAX>
12370 JSON_HEDLEY_NON_NULL(2)
12371 bool sax_parse_internal(SAX* sax)
12375 std::vector<bool> states;
12377 bool skip_to_state_evaluation =
false;
12381 if (!skip_to_state_evaluation)
12384 switch (last_token)
12386 case token_type::begin_object:
12388 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(
static_cast<std::size_t
>(-1))))
12394 if (get_token() == token_type::end_object)
12396 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12404 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12406 return sax->parse_error(m_lexer.get_position(),
12407 m_lexer.get_token_string(),
12408 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string,
"object key"),
nullptr));
12410 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12416 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12418 return sax->parse_error(m_lexer.get_position(),
12419 m_lexer.get_token_string(),
12420 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator,
"object separator"),
nullptr));
12424 states.push_back(
false);
12431 case token_type::begin_array:
12433 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(
static_cast<std::size_t
>(-1))))
12439 if (get_token() == token_type::end_array)
12441 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12449 states.push_back(
true);
12455 case token_type::value_float:
12457 const auto res = m_lexer.get_number_float();
12459 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12461 return sax->parse_error(m_lexer.get_position(),
12462 m_lexer.get_token_string(),
12463 out_of_range::create(406, concat(
"number overflow parsing '", m_lexer.get_token_string(),
'\''),
nullptr));
12466 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12474 case token_type::literal_false:
12476 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(
false)))
12483 case token_type::literal_null:
12485 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12492 case token_type::literal_true:
12494 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(
true)))
12501 case token_type::value_integer:
12503 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12510 case token_type::value_string:
12512 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12519 case token_type::value_unsigned:
12521 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12528 case token_type::parse_error:
12531 return sax->parse_error(m_lexer.get_position(),
12532 m_lexer.get_token_string(),
12533 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized,
"value"),
nullptr));
12535 case token_type::end_of_input:
12537 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12539 return sax->parse_error(m_lexer.get_position(),
12540 m_lexer.get_token_string(),
12541 parse_error::create(101, m_lexer.get_position(),
12542 "attempting to parse an empty input; check that your input string or stream contains the expected JSON",
nullptr));
12545 return sax->parse_error(m_lexer.get_position(),
12546 m_lexer.get_token_string(),
12547 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value,
"value"),
nullptr));
12549 case token_type::uninitialized:
12550 case token_type::end_array:
12551 case token_type::end_object:
12552 case token_type::name_separator:
12553 case token_type::value_separator:
12554 case token_type::literal_or_value:
12557 return sax->parse_error(m_lexer.get_position(),
12558 m_lexer.get_token_string(),
12559 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value,
"value"),
nullptr));
12565 skip_to_state_evaluation =
false;
12569 if (states.empty())
12578 if (get_token() == token_type::value_separator)
12586 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12588 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12597 JSON_ASSERT(!states.empty());
12599 skip_to_state_evaluation =
true;
12603 return sax->parse_error(m_lexer.get_position(),
12604 m_lexer.get_token_string(),
12605 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array,
"array"),
nullptr));
12611 if (get_token() == token_type::value_separator)
12614 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12616 return sax->parse_error(m_lexer.get_position(),
12617 m_lexer.get_token_string(),
12618 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string,
"object key"),
nullptr));
12621 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12627 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12629 return sax->parse_error(m_lexer.get_position(),
12630 m_lexer.get_token_string(),
12631 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator,
"object separator"),
nullptr));
12640 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12642 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12651 JSON_ASSERT(!states.empty());
12653 skip_to_state_evaluation =
true;
12657 return sax->parse_error(m_lexer.get_position(),
12658 m_lexer.get_token_string(),
12659 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object,
"object"),
nullptr));
12666 return last_token = m_lexer.scan();
12669 std::string exception_message(
const token_type expected,
const std::string& context)
12671 std::string error_msg =
"syntax error ";
12673 if (!context.empty())
12675 error_msg += concat(
"while parsing ", context,
' ');
12680 if (last_token == token_type::parse_error)
12682 error_msg += concat(m_lexer.get_error_message(),
"; last read: '",
12683 m_lexer.get_token_string(),
'\'');
12687 error_msg += concat(
"unexpected ", lexer_t::token_type_name(last_token));
12690 if (expected != token_type::uninitialized)
12692 error_msg += concat(
"; expected ", lexer_t::token_type_name(expected));
12700 const parser_callback_t<BasicJsonType> callback =
nullptr;
12702 token_type last_token = token_type::uninitialized;
12706 const bool allow_exceptions =
true;
12710NLOHMANN_JSON_NAMESPACE_END
12742NLOHMANN_JSON_NAMESPACE_BEGIN
12758 using difference_type = std::ptrdiff_t;
12759 static constexpr difference_type begin_value = 0;
12760 static constexpr difference_type end_value = begin_value + 1;
12762 JSON_PRIVATE_UNLESS_TESTED:
12764 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12767 constexpr difference_type get_value()
const noexcept
12775 m_it = begin_value;
12787 return m_it == begin_value;
12793 return m_it == end_value;
12798 return lhs.m_it == rhs.m_it;
12801 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
12803 return lhs.m_it < rhs.m_it;
12806 primitive_iterator_t operator+(difference_type n)
noexcept
12808 auto result = *
this;
12813 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs)
noexcept
12815 return lhs.m_it - rhs.m_it;
12818 primitive_iterator_t& operator++() noexcept
12824 primitive_iterator_t operator++(
int)&
noexcept
12826 auto result = *
this;
12831 primitive_iterator_t& operator--() noexcept
12837 primitive_iterator_t operator--(
int)&
noexcept
12839 auto result = *
this;
12844 primitive_iterator_t& operator+=(difference_type n)
noexcept
12850 primitive_iterator_t& operator-=(difference_type n)
noexcept
12858NLOHMANN_JSON_NAMESPACE_END
12861NLOHMANN_JSON_NAMESPACE_BEGIN
12874 typename BasicJsonType::object_t::iterator object_iterator {};
12876 typename BasicJsonType::array_t::iterator array_iterator {};
12882NLOHMANN_JSON_NAMESPACE_END
12896#include <type_traits>
12913NLOHMANN_JSON_NAMESPACE_BEGIN
12918template<
typename IteratorType>
class iteration_proxy;
12919template<
typename IteratorType>
class iteration_proxy_value;
12937template<
typename BasicJsonType>
12944 friend BasicJsonType;
12948 using object_t =
typename BasicJsonType::object_t;
12949 using array_t =
typename BasicJsonType::array_t;
12952 "iter_impl only accepts (const) basic_json");
12954 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12955 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12956 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12971 using pointer =
typename std::conditional<std::is_const<BasicJsonType>::value,
12972 typename BasicJsonType::const_pointer,
12973 typename BasicJsonType::pointer>::type;
12976 typename std::conditional<std::is_const<BasicJsonType>::value,
12977 typename BasicJsonType::const_reference,
12978 typename BasicJsonType::reference>::type;
12993 JSON_ASSERT(m_object !=
nullptr);
12995 switch (m_object->m_data.m_type)
12997 case value_t::object:
12999 m_it.object_iterator =
typename object_t::iterator();
13003 case value_t::array:
13005 m_it.array_iterator =
typename array_t::iterator();
13009 case value_t::null:
13010 case value_t::string:
13011 case value_t::boolean:
13012 case value_t::number_integer:
13013 case value_t::number_unsigned:
13014 case value_t::number_float:
13015 case value_t::binary:
13016 case value_t::discarded:
13042 : m_object(other.m_object), m_it(other.m_it)
13053 if (&other !=
this)
13055 m_object = other.m_object;
13067 : m_object(other.m_object), m_it(other.m_it)
13078 m_object = other.m_object;
13083 JSON_PRIVATE_UNLESS_TESTED:
13088 void set_begin() noexcept
13090 JSON_ASSERT(m_object !=
nullptr);
13092 switch (m_object->m_data.m_type)
13094 case value_t::object:
13096 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13100 case value_t::array:
13102 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13106 case value_t::null:
13109 m_it.primitive_iterator.set_end();
13113 case value_t::string:
13114 case value_t::boolean:
13115 case value_t::number_integer:
13116 case value_t::number_unsigned:
13117 case value_t::number_float:
13118 case value_t::binary:
13119 case value_t::discarded:
13122 m_it.primitive_iterator.set_begin();
13134 JSON_ASSERT(m_object !=
nullptr);
13136 switch (m_object->m_data.m_type)
13138 case value_t::object:
13140 m_it.object_iterator = m_object->m_data.m_value.object->end();
13144 case value_t::array:
13146 m_it.array_iterator = m_object->m_data.m_value.array->end();
13150 case value_t::null:
13151 case value_t::string:
13152 case value_t::boolean:
13153 case value_t::number_integer:
13154 case value_t::number_unsigned:
13155 case value_t::number_float:
13156 case value_t::binary:
13157 case value_t::discarded:
13160 m_it.primitive_iterator.set_end();
13173 JSON_ASSERT(m_object !=
nullptr);
13175 switch (m_object->m_data.m_type)
13177 case value_t::object:
13179 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13180 return m_it.object_iterator->second;
13183 case value_t::array:
13185 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13186 return *m_it.array_iterator;
13189 case value_t::null:
13190 JSON_THROW(invalid_iterator::create(214,
"cannot get value", m_object));
13192 case value_t::string:
13193 case value_t::boolean:
13194 case value_t::number_integer:
13195 case value_t::number_unsigned:
13196 case value_t::number_float:
13197 case value_t::binary:
13198 case value_t::discarded:
13201 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13206 JSON_THROW(invalid_iterator::create(214,
"cannot get value", m_object));
13217 JSON_ASSERT(m_object !=
nullptr);
13219 switch (m_object->m_data.m_type)
13221 case value_t::object:
13223 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13224 return &(m_it.object_iterator->second);
13227 case value_t::array:
13229 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13230 return &*m_it.array_iterator;
13233 case value_t::null:
13234 case value_t::string:
13235 case value_t::boolean:
13236 case value_t::number_integer:
13237 case value_t::number_unsigned:
13238 case value_t::number_float:
13239 case value_t::binary:
13240 case value_t::discarded:
13243 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13248 JSON_THROW(invalid_iterator::create(214,
"cannot get value", m_object));
13259 auto result = *
this;
13270 JSON_ASSERT(m_object !=
nullptr);
13272 switch (m_object->m_data.m_type)
13274 case value_t::object:
13276 std::advance(m_it.object_iterator, 1);
13280 case value_t::array:
13282 std::advance(m_it.array_iterator, 1);
13286 case value_t::null:
13287 case value_t::string:
13288 case value_t::boolean:
13289 case value_t::number_integer:
13290 case value_t::number_unsigned:
13291 case value_t::number_float:
13292 case value_t::binary:
13293 case value_t::discarded:
13296 ++m_it.primitive_iterator;
13310 auto result = *
this;
13321 JSON_ASSERT(m_object !=
nullptr);
13323 switch (m_object->m_data.m_type)
13325 case value_t::object:
13327 std::advance(m_it.object_iterator, -1);
13331 case value_t::array:
13333 std::advance(m_it.array_iterator, -1);
13337 case value_t::null:
13338 case value_t::string:
13339 case value_t::boolean:
13340 case value_t::number_integer:
13341 case value_t::number_unsigned:
13342 case value_t::number_float:
13343 case value_t::binary:
13344 case value_t::discarded:
13347 --m_it.primitive_iterator;
13359 template <
typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::
nullptr_t > =
nullptr >
13363 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13365 JSON_THROW(invalid_iterator::create(212,
"cannot compare iterators of different containers", m_object));
13368 JSON_ASSERT(m_object !=
nullptr);
13370 switch (m_object->m_data.m_type)
13372 case value_t::object:
13373 return (m_it.object_iterator == other.m_it.object_iterator);
13375 case value_t::array:
13376 return (m_it.array_iterator == other.m_it.array_iterator);
13378 case value_t::null:
13379 case value_t::string:
13380 case value_t::boolean:
13381 case value_t::number_integer:
13382 case value_t::number_unsigned:
13383 case value_t::number_float:
13384 case value_t::binary:
13385 case value_t::discarded:
13387 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13395 template <
typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::
nullptr_t > =
nullptr >
13398 return !operator==(other);
13408 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13410 JSON_THROW(invalid_iterator::create(212,
"cannot compare iterators of different containers", m_object));
13413 JSON_ASSERT(m_object !=
nullptr);
13415 switch (m_object->m_data.m_type)
13417 case value_t::object:
13418 JSON_THROW(invalid_iterator::create(213,
"cannot compare order of object iterators", m_object));
13420 case value_t::array:
13423 case value_t::null:
13424 case value_t::string:
13425 case value_t::boolean:
13426 case value_t::number_integer:
13427 case value_t::number_unsigned:
13428 case value_t::number_float:
13429 case value_t::binary:
13430 case value_t::discarded:
13442 return !other.operator < (*this);
13451 return !operator<=(other);
13469 JSON_ASSERT(m_object !=
nullptr);
13471 switch (m_object->m_data.m_type)
13473 case value_t::object:
13474 JSON_THROW(invalid_iterator::create(209,
"cannot use offsets with object iterators", m_object));
13476 case value_t::array:
13478 std::advance(m_it.array_iterator, i);
13482 case value_t::null:
13483 case value_t::string:
13484 case value_t::boolean:
13485 case value_t::number_integer:
13486 case value_t::number_unsigned:
13487 case value_t::number_float:
13488 case value_t::binary:
13489 case value_t::discarded:
13492 m_it.primitive_iterator += i;
13506 return operator+=(-i);
13515 auto result = *
this;
13537 auto result = *
this;
13548 JSON_ASSERT(m_object !=
nullptr);
13550 switch (m_object->m_data.m_type)
13552 case value_t::object:
13553 JSON_THROW(invalid_iterator::create(209,
"cannot use offsets with object iterators", m_object));
13555 case value_t::array:
13558 case value_t::null:
13559 case value_t::string:
13560 case value_t::boolean:
13561 case value_t::number_integer:
13562 case value_t::number_unsigned:
13563 case value_t::number_float:
13564 case value_t::binary:
13565 case value_t::discarded:
13577 JSON_ASSERT(m_object !=
nullptr);
13579 switch (m_object->m_data.m_type)
13581 case value_t::object:
13582 JSON_THROW(invalid_iterator::create(208,
"cannot use operator[] for object iterators", m_object));
13584 case value_t::array:
13585 return *std::next(m_it.array_iterator, n);
13587 case value_t::null:
13588 JSON_THROW(invalid_iterator::create(214,
"cannot get value", m_object));
13590 case value_t::string:
13591 case value_t::boolean:
13592 case value_t::number_integer:
13593 case value_t::number_unsigned:
13594 case value_t::number_float:
13595 case value_t::binary:
13596 case value_t::discarded:
13599 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13604 JSON_THROW(invalid_iterator::create(214,
"cannot get value", m_object));
13613 const typename object_t::key_type&
key()
const
13615 JSON_ASSERT(m_object !=
nullptr);
13617 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13619 return m_it.object_iterator->first;
13622 JSON_THROW(invalid_iterator::create(207,
"cannot use key() for non-object iterators", m_object));
13631 return operator*();
13634 JSON_PRIVATE_UNLESS_TESTED:
13636 pointer m_object =
nullptr;
13642NLOHMANN_JSON_NAMESPACE_END
13664NLOHMANN_JSON_NAMESPACE_BEGIN
13690template<
typename Base>
13694 using difference_type = std::ptrdiff_t;
13758 return *(this->operator+(n));
13762 auto key() const -> decltype(std::declval<Base>().key())
13764 auto it = --this->base();
13771 auto it = --this->base();
13772 return it.operator * ();
13777NLOHMANN_JSON_NAMESPACE_END
13792#include <type_traits>
13797NLOHMANN_JSON_NAMESPACE_BEGIN
13814using json_base_class =
typename std::conditional <
13815 std::is_same<T, void>::value,
13821NLOHMANN_JSON_NAMESPACE_END
13834#include <algorithm>
13858NLOHMANN_JSON_NAMESPACE_BEGIN
13862template<
typename RefStringType>
13866 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13872 template<
typename T>
13878 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13881 using type = StringType;
13886 using string_t =
typename string_t_helper<RefStringType>::type;
13891 : reference_tokens(split(s))
13898 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13900 [](
const string_t& a,
const string_t& b)
13902 return detail::concat(a,
'/', detail::escape(b));
13908 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13909 operator string_t()
const
13911 return to_string();
13928 reference_tokens.insert(reference_tokens.end(),
13929 ptr.reference_tokens.begin(),
13930 ptr.reference_tokens.end());
13938 push_back(std::move(token));
13946 return *
this /= std::to_string(array_idx);
13989 if (JSON_HEDLEY_UNLIKELY(empty()))
13991 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent",
nullptr));
13994 reference_tokens.pop_back();
14001 if (JSON_HEDLEY_UNLIKELY(empty()))
14003 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent",
nullptr));
14006 return reference_tokens.back();
14013 reference_tokens.push_back(token);
14020 reference_tokens.push_back(std::move(token));
14027 return reference_tokens.empty();
14041 template<
typename BasicJsonType>
14044 using size_type =
typename BasicJsonType::size_type;
14047 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] ==
'0'))
14053 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >=
'1' && s[0] <=
'9')))
14058 const char* p = s.c_str();
14059 char* p_end =
nullptr;
14061 const unsigned long long res = std::strtoull(p, &p_end, 10);
14064 || JSON_HEDLEY_UNLIKELY(
static_cast<std::size_t
>(p_end - p) != s.size()))
14066 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", s,
"'"),
nullptr));
14071 if (res >=
static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))
14073 JSON_THROW(detail::out_of_range::create(410, detail::concat(
"array index ", s,
" exceeds size_type"),
nullptr));
14076 return static_cast<size_type
>(res);
14079 JSON_PRIVATE_UNLESS_TESTED:
14082 if (JSON_HEDLEY_UNLIKELY(empty()))
14084 JSON_THROW(detail::out_of_range::create(405,
"JSON pointer has no parent",
nullptr));
14088 result.reference_tokens = {reference_tokens[0]};
14101 template<
typename BasicJsonType>
14108 for (
const auto& reference_token : reference_tokens)
14110 switch (result->type())
14114 if (reference_token ==
"0")
14117 result = &result->operator[](0);
14122 result = &result->operator[](reference_token);
14130 result = &result->operator[](reference_token);
14137 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14155 JSON_THROW(detail::type_error::create(313,
"invalid value to unflatten", &j));
14181 template<
typename BasicJsonType>
14184 for (
const auto& reference_token : reference_tokens)
14187 if (ptr->is_null())
14191 std::all_of(reference_token.begin(), reference_token.end(),
14192 [](
const unsigned char x)
14194 return std::isdigit(x);
14198 *ptr = (nums || reference_token ==
"-")
14203 switch (ptr->type())
14208 ptr = &ptr->operator[](reference_token);
14214 if (reference_token ==
"-")
14217 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14222 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14236 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
14249 template<
typename BasicJsonType>
14252 for (
const auto& reference_token : reference_tokens)
14254 switch (ptr->type())
14259 ptr = &ptr->at(reference_token);
14265 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
14268 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14269 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14270 ") is out of range"), ptr));
14274 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14287 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
14307 template<
typename BasicJsonType>
14310 for (
const auto& reference_token : reference_tokens)
14312 switch (ptr->type())
14317 ptr = &ptr->operator[](reference_token);
14323 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
14326 JSON_THROW(detail::out_of_range::create(402, detail::concat(
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
") is out of range"), ptr));
14330 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14343 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
14356 template<
typename BasicJsonType>
14359 for (
const auto& reference_token : reference_tokens)
14361 switch (ptr->type())
14366 ptr = &ptr->at(reference_token);
14372 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
14375 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14376 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14377 ") is out of range"), ptr));
14381 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14394 JSON_THROW(detail::out_of_range::create(404, detail::concat(
"unresolved reference token '", reference_token,
"'"), ptr));
14405 template<
typename BasicJsonType>
14408 for (
const auto& reference_token : reference_tokens)
14410 switch (ptr->type())
14414 if (!ptr->contains(reference_token))
14420 ptr = &ptr->operator[](reference_token);
14426 if (JSON_HEDLEY_UNLIKELY(reference_token ==
"-"))
14431 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !(
"0" <= reference_token && reference_token <=
"9")))
14436 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14438 if (JSON_HEDLEY_UNLIKELY(!(
'1' <= reference_token[0] && reference_token[0] <=
'9')))
14443 for (std::size_t i = 1; i < reference_token.size(); i++)
14445 if (JSON_HEDLEY_UNLIKELY(!(
'0' <= reference_token[i] && reference_token[i] <=
'9')))
14453 const auto idx = array_index<BasicJsonType>(reference_token);
14454 if (idx >= ptr->size())
14460 ptr = &ptr->operator[](idx);
14494 static std::vector<string_t>
split(
const string_t& reference_string)
14496 std::vector<string_t> result;
14499 if (reference_string.empty())
14505 if (JSON_HEDLEY_UNLIKELY(reference_string[0] !=
'/'))
14507 JSON_THROW(
detail::parse_error::create(107, 1, detail::concat(
"JSON pointer must be empty or begin with '/' - was: '", reference_string,
"'"),
nullptr));
14515 std::size_t slash = reference_string.find_first_of(
'/', 1),
14522 start = (slash == string_t::npos) ? 0 : slash + 1,
14524 slash = reference_string.find_first_of(
'/', start))
14528 auto reference_token = reference_string.substr(start, slash - start);
14531 for (std::size_t pos = reference_token.find_first_of(
'~');
14532 pos != string_t::npos;
14533 pos = reference_token.find_first_of(
'~', pos + 1))
14535 JSON_ASSERT(reference_token[pos] ==
'~');
14538 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14539 (reference_token[pos + 1] !=
'0' &&
14540 reference_token[pos + 1] !=
'1')))
14548 result.push_back(reference_token);
14562 template<
typename BasicJsonType>
14564 const BasicJsonType& value,
14565 BasicJsonType& result)
14567 switch (value.type())
14571 if (value.m_data.m_value.array->empty())
14574 result[reference_string] =
nullptr;
14579 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14581 flatten(detail::concat(reference_string,
'/', std::to_string(i)),
14582 value.m_data.m_value.array->operator[](i), result);
14590 if (value.m_data.m_value.object->empty())
14593 result[reference_string] =
nullptr;
14598 for (
const auto& element : *value.m_data.m_value.object)
14600 flatten(detail::concat(reference_string,
'/',
detail::escape(element.first)), element.second, result);
14617 result[reference_string] = value;
14633 template<
typename BasicJsonType>
14634 static BasicJsonType
14637 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14639 JSON_THROW(detail::type_error::create(314,
"only objects can be unflattened", &value));
14642 BasicJsonType result;
14645 for (
const auto& element : *value.m_data.m_value.object)
14647 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14649 JSON_THROW(detail::type_error::create(315,
"values in object must be primitive", &element.second));
14666 result.reference_tokens = reference_tokens;
14673 result.reference_tokens = std::move(reference_tokens);
14678#if JSON_HAS_THREE_WAY_COMPARISON
14681 template<
typename RefStringTypeRhs>
14684 return reference_tokens == rhs.reference_tokens;
14689 JSON_HEDLEY_DEPRECATED_FOR(3.11.2,
operator==(
json_pointer))
14690 bool operator==(
const string_t& rhs)
const
14696 template<
typename RefStringTypeRhs>
14699 return reference_tokens <=> rhs.reference_tokens;
14704 template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
14711 template<
typename RefStringTypeLhs,
typename StringType>
14714 const StringType& rhs);
14718 template<
typename RefStringTypeRhs,
typename StringType>
14720 friend bool operator==(
const StringType& lhs,
14725 template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
14732 template<
typename RefStringTypeLhs,
typename StringType>
14735 const StringType& rhs);
14739 template<
typename RefStringTypeRhs,
typename StringType>
14741 friend bool operator!=(
const StringType& lhs,
14745 template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
14756#if !JSON_HAS_THREE_WAY_COMPARISON
14758template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
14762 return lhs.reference_tokens == rhs.reference_tokens;
14765template<
typename RefStringTypeLhs,
14766 typename StringType =
typename json_pointer<RefStringTypeLhs>::string_t>
14769 const StringType& rhs)
14774template<
typename RefStringTypeRhs,
14775 typename StringType =
typename json_pointer<RefStringTypeRhs>::string_t>
14777inline
bool operator==(const StringType& lhs,
14783template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
14787 return !(lhs == rhs);
14790template<
typename RefStringTypeLhs,
14791 typename StringType =
typename json_pointer<RefStringTypeLhs>::string_t>
14794 const StringType& rhs)
14796 return !(lhs == rhs);
14799template<
typename RefStringTypeRhs,
14800 typename StringType =
typename json_pointer<RefStringTypeRhs>::string_t>
14802inline
bool operator!=(const StringType& lhs,
14805 return !(lhs == rhs);
14808template<
typename RefStringTypeLhs,
typename RefStringTypeRhs>
14812 return lhs.reference_tokens < rhs.reference_tokens;
14816NLOHMANN_JSON_NAMESPACE_END
14829#include <initializer_list>
14837NLOHMANN_JSON_NAMESPACE_BEGIN
14841template<
typename BasicJsonType>
14845 using value_type = BasicJsonType;
14848 : owned_value(std::move(
value))
14852 : value_ref(&
value)
14855 json_ref(std::initializer_list<json_ref> init)
14856 : owned_value(init)
14861 enable_if_t<std::is_constructible<value_type, Args...>::value,
int> = 0 >
14863 : owned_value(std::forward<Args>(args)...)
14873 value_type moved_or_copied()
const
14875 if (value_ref ==
nullptr)
14877 return std::move(owned_value);
14882 value_type
const& operator*()
const
14884 return value_ref ? *value_ref : owned_value;
14887 value_type
const* operator->()
const
14893 mutable value_type owned_value =
nullptr;
14894 value_type
const* value_ref =
nullptr;
14898NLOHMANN_JSON_NAMESPACE_END
14921#include <algorithm>
14947#include <algorithm>
14962NLOHMANN_JSON_NAMESPACE_BEGIN
14969 virtual void write_character(CharType c) = 0;
14970 virtual void write_characters(
const CharType* s, std::size_t length) = 0;
14981template<
typename CharType>
14985template<
typename CharType,
typename AllocatorType = std::allocator<CharType>>
14993 void write_character(CharType c)
override
14998 JSON_HEDLEY_NON_NULL(2)
14999 void write_characters(
const CharType* s, std::size_t length)
override
15001 v.insert(v.end(), s, s + length);
15005 std::vector<CharType, AllocatorType>& v;
15010template<
typename CharType>
15018 void write_character(CharType c)
override
15023 JSON_HEDLEY_NON_NULL(2)
15024 void write_characters(
const CharType* s, std::size_t length)
override
15026 stream.write(s,
static_cast<std::streamsize
>(length));
15030 std::basic_ostream<CharType>& stream;
15035template<
typename CharType,
typename StringType = std::basic_
string<CharType>>
15043 void write_character(CharType c)
override
15048 JSON_HEDLEY_NON_NULL(2)
15049 void write_characters(
const CharType* s, std::size_t length)
override
15051 str.append(s, length);
15058template<
typename CharType,
typename StringType = std::basic_
string<CharType>>
15062 template<
typename AllocatorType = std::allocator<CharType>>
15084NLOHMANN_JSON_NAMESPACE_END
15089NLOHMANN_JSON_NAMESPACE_BEGIN
15100template<
typename BasicJsonType,
typename CharType>
15103 using string_t =
typename BasicJsonType::string_t;
15104 using binary_t =
typename BasicJsonType::binary_t;
15105 using number_float_t =
typename BasicJsonType::number_float_t;
15126 case value_t::object:
15128 write_bson_object(*j.m_data.m_value.object);
15132 case value_t::null:
15133 case value_t::array:
15134 case value_t::string:
15135 case value_t::boolean:
15136 case value_t::number_integer:
15137 case value_t::number_unsigned:
15138 case value_t::number_float:
15139 case value_t::binary:
15140 case value_t::discarded:
15143 JSON_THROW(type_error::create(317, concat(
"to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15155 case value_t::null:
15157 oa->write_character(to_char_type(0xF6));
15161 case value_t::boolean:
15163 oa->write_character(j.m_data.m_value.boolean
15164 ? to_char_type(0xF5)
15165 : to_char_type(0xF4));
15169 case value_t::number_integer:
15171 if (j.m_data.m_value.number_integer >= 0)
15176 if (j.m_data.m_value.number_integer <= 0x17)
15178 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_integer));
15180 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15182 oa->write_character(to_char_type(0x18));
15183 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_integer));
15185 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15187 oa->write_character(to_char_type(0x19));
15188 write_number(
static_cast<std::uint16_t
>(j.m_data.m_value.number_integer));
15190 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15192 oa->write_character(to_char_type(0x1A));
15193 write_number(
static_cast<std::uint32_t
>(j.m_data.m_value.number_integer));
15197 oa->write_character(to_char_type(0x1B));
15198 write_number(
static_cast<std::uint64_t
>(j.m_data.m_value.number_integer));
15205 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15206 if (j.m_data.m_value.number_integer >= -24)
15208 write_number(
static_cast<std::uint8_t
>(0x20 + positive_number));
15210 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15212 oa->write_character(to_char_type(0x38));
15213 write_number(
static_cast<std::uint8_t
>(positive_number));
15215 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15217 oa->write_character(to_char_type(0x39));
15218 write_number(
static_cast<std::uint16_t
>(positive_number));
15220 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15222 oa->write_character(to_char_type(0x3A));
15223 write_number(
static_cast<std::uint32_t
>(positive_number));
15227 oa->write_character(to_char_type(0x3B));
15228 write_number(
static_cast<std::uint64_t
>(positive_number));
15234 case value_t::number_unsigned:
15236 if (j.m_data.m_value.number_unsigned <= 0x17)
15238 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_unsigned));
15240 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15242 oa->write_character(to_char_type(0x18));
15243 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_unsigned));
15245 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15247 oa->write_character(to_char_type(0x19));
15248 write_number(
static_cast<std::uint16_t
>(j.m_data.m_value.number_unsigned));
15250 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15252 oa->write_character(to_char_type(0x1A));
15253 write_number(
static_cast<std::uint32_t
>(j.m_data.m_value.number_unsigned));
15257 oa->write_character(to_char_type(0x1B));
15258 write_number(
static_cast<std::uint64_t
>(j.m_data.m_value.number_unsigned));
15263 case value_t::number_float:
15265 if (std::isnan(j.m_data.m_value.number_float))
15268 oa->write_character(to_char_type(0xF9));
15269 oa->write_character(to_char_type(0x7E));
15270 oa->write_character(to_char_type(0x00));
15272 else if (std::isinf(j.m_data.m_value.number_float))
15275 oa->write_character(to_char_type(0xf9));
15276 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15277 oa->write_character(to_char_type(0x00));
15281 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15286 case value_t::string:
15289 const auto N = j.m_data.m_value.string->size();
15292 write_number(
static_cast<std::uint8_t
>(0x60 + N));
15294 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15296 oa->write_character(to_char_type(0x78));
15297 write_number(
static_cast<std::uint8_t
>(N));
15299 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15301 oa->write_character(to_char_type(0x79));
15302 write_number(
static_cast<std::uint16_t
>(N));
15304 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15306 oa->write_character(to_char_type(0x7A));
15307 write_number(
static_cast<std::uint32_t
>(N));
15310 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15312 oa->write_character(to_char_type(0x7B));
15313 write_number(
static_cast<std::uint64_t
>(N));
15318 oa->write_characters(
15319 reinterpret_cast<const CharType*
>(j.m_data.m_value.string->c_str()),
15320 j.m_data.m_value.string->size());
15324 case value_t::array:
15327 const auto N = j.m_data.m_value.array->size();
15330 write_number(
static_cast<std::uint8_t
>(0x80 + N));
15332 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15334 oa->write_character(to_char_type(0x98));
15335 write_number(
static_cast<std::uint8_t
>(N));
15337 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15339 oa->write_character(to_char_type(0x99));
15340 write_number(
static_cast<std::uint16_t
>(N));
15342 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15344 oa->write_character(to_char_type(0x9A));
15345 write_number(
static_cast<std::uint32_t
>(N));
15348 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15350 oa->write_character(to_char_type(0x9B));
15351 write_number(
static_cast<std::uint64_t
>(N));
15356 for (
const auto& el : *j.m_data.m_value.array)
15363 case value_t::binary:
15365 if (j.m_data.m_value.binary->has_subtype())
15367 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15369 write_number(
static_cast<std::uint8_t
>(0xd8));
15370 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.binary->subtype()));
15372 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15374 write_number(
static_cast<std::uint8_t
>(0xd9));
15375 write_number(
static_cast<std::uint16_t
>(j.m_data.m_value.binary->subtype()));
15377 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15379 write_number(
static_cast<std::uint8_t
>(0xda));
15380 write_number(
static_cast<std::uint32_t
>(j.m_data.m_value.binary->subtype()));
15382 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15384 write_number(
static_cast<std::uint8_t
>(0xdb));
15385 write_number(
static_cast<std::uint64_t
>(j.m_data.m_value.binary->subtype()));
15390 const auto N = j.m_data.m_value.binary->size();
15393 write_number(
static_cast<std::uint8_t
>(0x40 + N));
15395 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15397 oa->write_character(to_char_type(0x58));
15398 write_number(
static_cast<std::uint8_t
>(N));
15400 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15402 oa->write_character(to_char_type(0x59));
15403 write_number(
static_cast<std::uint16_t
>(N));
15405 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15407 oa->write_character(to_char_type(0x5A));
15408 write_number(
static_cast<std::uint32_t
>(N));
15411 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15413 oa->write_character(to_char_type(0x5B));
15414 write_number(
static_cast<std::uint64_t
>(N));
15419 oa->write_characters(
15420 reinterpret_cast<const CharType*
>(j.m_data.m_value.binary->data()),
15426 case value_t::object:
15429 const auto N = j.m_data.m_value.object->size();
15432 write_number(
static_cast<std::uint8_t
>(0xA0 + N));
15434 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15436 oa->write_character(to_char_type(0xB8));
15437 write_number(
static_cast<std::uint8_t
>(N));
15439 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15441 oa->write_character(to_char_type(0xB9));
15442 write_number(
static_cast<std::uint16_t
>(N));
15444 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15446 oa->write_character(to_char_type(0xBA));
15447 write_number(
static_cast<std::uint32_t
>(N));
15450 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15452 oa->write_character(to_char_type(0xBB));
15453 write_number(
static_cast<std::uint64_t
>(N));
15458 for (
const auto& el : *j.m_data.m_value.object)
15460 write_cbor(el.first);
15461 write_cbor(el.second);
15466 case value_t::discarded:
15479 case value_t::null:
15481 oa->write_character(to_char_type(0xC0));
15485 case value_t::boolean:
15487 oa->write_character(j.m_data.m_value.boolean
15488 ? to_char_type(0xC3)
15489 : to_char_type(0xC2));
15493 case value_t::number_integer:
15495 if (j.m_data.m_value.number_integer >= 0)
15500 if (j.m_data.m_value.number_unsigned < 128)
15503 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_integer));
15505 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15508 oa->write_character(to_char_type(0xCC));
15509 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_integer));
15511 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15514 oa->write_character(to_char_type(0xCD));
15515 write_number(
static_cast<std::uint16_t
>(j.m_data.m_value.number_integer));
15517 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15520 oa->write_character(to_char_type(0xCE));
15521 write_number(
static_cast<std::uint32_t
>(j.m_data.m_value.number_integer));
15523 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15526 oa->write_character(to_char_type(0xCF));
15527 write_number(
static_cast<std::uint64_t
>(j.m_data.m_value.number_integer));
15532 if (j.m_data.m_value.number_integer >= -32)
15535 write_number(
static_cast<std::int8_t
>(j.m_data.m_value.number_integer));
15537 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15538 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15541 oa->write_character(to_char_type(0xD0));
15542 write_number(
static_cast<std::int8_t
>(j.m_data.m_value.number_integer));
15544 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15545 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15548 oa->write_character(to_char_type(0xD1));
15549 write_number(
static_cast<std::int16_t
>(j.m_data.m_value.number_integer));
15551 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15552 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15555 oa->write_character(to_char_type(0xD2));
15556 write_number(
static_cast<std::int32_t
>(j.m_data.m_value.number_integer));
15558 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15559 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15562 oa->write_character(to_char_type(0xD3));
15563 write_number(
static_cast<std::int64_t
>(j.m_data.m_value.number_integer));
15569 case value_t::number_unsigned:
15571 if (j.m_data.m_value.number_unsigned < 128)
15574 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_integer));
15576 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15579 oa->write_character(to_char_type(0xCC));
15580 write_number(
static_cast<std::uint8_t
>(j.m_data.m_value.number_integer));
15582 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15585 oa->write_character(to_char_type(0xCD));
15586 write_number(
static_cast<std::uint16_t
>(j.m_data.m_value.number_integer));
15588 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15591 oa->write_character(to_char_type(0xCE));
15592 write_number(
static_cast<std::uint32_t
>(j.m_data.m_value.number_integer));
15594 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15597 oa->write_character(to_char_type(0xCF));
15598 write_number(
static_cast<std::uint64_t
>(j.m_data.m_value.number_integer));
15603 case value_t::number_float:
15605 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15609 case value_t::string:
15612 const auto N = j.m_data.m_value.string->size();
15616 write_number(
static_cast<std::uint8_t
>(0xA0 | N));
15618 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15621 oa->write_character(to_char_type(0xD9));
15622 write_number(
static_cast<std::uint8_t
>(N));
15624 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15627 oa->write_character(to_char_type(0xDA));
15628 write_number(
static_cast<std::uint16_t
>(N));
15630 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15633 oa->write_character(to_char_type(0xDB));
15634 write_number(
static_cast<std::uint32_t
>(N));
15638 oa->write_characters(
15639 reinterpret_cast<const CharType*
>(j.m_data.m_value.string->c_str()),
15640 j.m_data.m_value.string->size());
15644 case value_t::array:
15647 const auto N = j.m_data.m_value.array->size();
15651 write_number(
static_cast<std::uint8_t
>(0x90 | N));
15653 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15656 oa->write_character(to_char_type(0xDC));
15657 write_number(
static_cast<std::uint16_t
>(N));
15659 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15662 oa->write_character(to_char_type(0xDD));
15663 write_number(
static_cast<std::uint32_t
>(N));
15667 for (
const auto& el : *j.m_data.m_value.array)
15674 case value_t::binary:
15678 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15681 const auto N = j.m_data.m_value.binary->size();
15682 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15684 std::uint8_t output_type{};
15691 output_type = 0xD4;
15694 output_type = 0xD5;
15697 output_type = 0xD6;
15700 output_type = 0xD7;
15703 output_type = 0xD8;
15706 output_type = 0xC7;
15714 output_type = 0xC4;
15718 oa->write_character(to_char_type(output_type));
15721 write_number(
static_cast<std::uint8_t
>(N));
15724 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15726 const std::uint8_t output_type = use_ext
15730 oa->write_character(to_char_type(output_type));
15731 write_number(
static_cast<std::uint16_t
>(N));
15733 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15735 const std::uint8_t output_type = use_ext
15739 oa->write_character(to_char_type(output_type));
15740 write_number(
static_cast<std::uint32_t
>(N));
15746 write_number(
static_cast<std::int8_t
>(j.m_data.m_value.binary->subtype()));
15750 oa->write_characters(
15751 reinterpret_cast<const CharType*
>(j.m_data.m_value.binary->data()),
15757 case value_t::object:
15760 const auto N = j.m_data.m_value.object->size();
15764 write_number(
static_cast<std::uint8_t
>(0x80 | (N & 0xF)));
15766 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15769 oa->write_character(to_char_type(0xDE));
15770 write_number(
static_cast<std::uint16_t
>(N));
15772 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15775 oa->write_character(to_char_type(0xDF));
15776 write_number(
static_cast<std::uint32_t
>(N));
15780 for (
const auto& el : *j.m_data.m_value.object)
15782 write_msgpack(el.first);
15783 write_msgpack(el.second);
15788 case value_t::discarded:
15802 const bool use_type,
const bool add_prefix =
true,
15803 const bool use_bjdata =
false)
15807 case value_t::null:
15811 oa->write_character(to_char_type(
'Z'));
15816 case value_t::boolean:
15820 oa->write_character(j.m_data.m_value.boolean
15821 ? to_char_type(
'T')
15822 : to_char_type(
'F'));
15827 case value_t::number_integer:
15829 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15833 case value_t::number_unsigned:
15835 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15839 case value_t::number_float:
15841 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15845 case value_t::string:
15849 oa->write_character(to_char_type(
'S'));
15851 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(),
true, use_bjdata);
15852 oa->write_characters(
15853 reinterpret_cast<const CharType*
>(j.m_data.m_value.string->c_str()),
15854 j.m_data.m_value.string->size());
15858 case value_t::array:
15862 oa->write_character(to_char_type(
'['));
15865 bool prefix_required =
true;
15866 if (use_type && !j.m_data.m_value.array->empty())
15868 JSON_ASSERT(use_count);
15869 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15870 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15871 [
this, first_prefix, use_bjdata](
const BasicJsonType & v)
15873 return ubjson_prefix(v, use_bjdata) == first_prefix;
15876 std::vector<CharType> bjdx = {
'[',
'{',
'S',
'H',
'T',
'F',
'N',
'Z'};
15878 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15880 prefix_required =
false;
15881 oa->write_character(to_char_type(
'$'));
15882 oa->write_character(first_prefix);
15888 oa->write_character(to_char_type(
'#'));
15889 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(),
true, use_bjdata);
15892 for (
const auto& el : *j.m_data.m_value.array)
15894 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15899 oa->write_character(to_char_type(
']'));
15905 case value_t::binary:
15909 oa->write_character(to_char_type(
'['));
15912 if (use_type && !j.m_data.m_value.binary->empty())
15914 JSON_ASSERT(use_count);
15915 oa->write_character(to_char_type(
'$'));
15916 oa->write_character(
'U');
15921 oa->write_character(to_char_type(
'#'));
15922 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(),
true, use_bjdata);
15927 oa->write_characters(
15928 reinterpret_cast<const CharType*
>(j.m_data.m_value.binary->data()),
15929 j.m_data.m_value.binary->size());
15933 for (
size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15935 oa->write_character(to_char_type(
'U'));
15936 oa->write_character(j.m_data.m_value.binary->data()[i]);
15942 oa->write_character(to_char_type(
']'));
15948 case value_t::object:
15950 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find(
"_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find(
"_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find(
"_ArrayData_") != j.m_data.m_value.object->end())
15952 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type))
15960 oa->write_character(to_char_type(
'{'));
15963 bool prefix_required =
true;
15964 if (use_type && !j.m_data.m_value.object->empty())
15966 JSON_ASSERT(use_count);
15967 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15968 const bool same_prefix = std::all_of(j.begin(), j.end(),
15969 [
this, first_prefix, use_bjdata](
const BasicJsonType & v)
15971 return ubjson_prefix(v, use_bjdata) == first_prefix;
15974 std::vector<CharType> bjdx = {
'[',
'{',
'S',
'H',
'T',
'F',
'N',
'Z'};
15976 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15978 prefix_required =
false;
15979 oa->write_character(to_char_type(
'$'));
15980 oa->write_character(first_prefix);
15986 oa->write_character(to_char_type(
'#'));
15987 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(),
true, use_bjdata);
15990 for (
const auto& el : *j.m_data.m_value.object)
15992 write_number_with_ubjson_prefix(el.first.size(),
true, use_bjdata);
15993 oa->write_characters(
15994 reinterpret_cast<const CharType*
>(el.first.c_str()),
15996 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
16001 oa->write_character(to_char_type(
'}'));
16007 case value_t::discarded:
16024 const auto it = name.find(
static_cast<typename string_t::value_type
>(0));
16025 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16027 JSON_THROW(out_of_range::create(409, concat(
"BSON key cannot contain code point U+0000 (at byte ", std::to_string(it),
")"), &j));
16028 static_cast<void>(j);
16031 return 1ul + name.size() + 1u;
16038 const std::uint8_t element_type)
16040 oa->write_character(to_char_type(element_type));
16041 oa->write_characters(
16042 reinterpret_cast<const CharType*
>(name.c_str()),
16052 write_bson_entry_header(name, 0x08);
16053 oa->write_character(
value ? to_char_type(0x01) : to_char_type(0x00));
16060 const double value)
16062 write_bson_entry_header(name, 0x01);
16063 write_number<double>(
value,
true);
16071 return sizeof(std::int32_t) +
value.size() + 1ul;
16078 const string_t& value)
16080 write_bson_entry_header(name, 0x02);
16082 write_number<std::int32_t>(
static_cast<std::int32_t
>(
value.size() + 1ul),
true);
16083 oa->write_characters(
16084 reinterpret_cast<const CharType*
>(
value.c_str()),
16093 write_bson_entry_header(name, 0x0A);
16101 return (std::numeric_limits<std::int32_t>::min)() <=
value &&
value <= (std::numeric_limits<std::int32_t>::max)()
16102 ?
sizeof(std::int32_t)
16103 :
sizeof(std::int64_t);
16110 const std::int64_t value)
16112 if ((std::numeric_limits<std::int32_t>::min)() <=
value &&
value <= (std::numeric_limits<std::int32_t>::max)())
16114 write_bson_entry_header(name, 0x10);
16115 write_number<std::int32_t>(
static_cast<std::int32_t
>(
value),
true);
16119 write_bson_entry_header(name, 0x12);
16120 write_number<std::int64_t>(
static_cast<std::int64_t
>(
value),
true);
16129 return (
value <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int32_t>::max)()))
16130 ?
sizeof(std::int32_t)
16131 :
sizeof(std::int64_t);
16138 const BasicJsonType& j)
16140 if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int32_t>::max)()))
16142 write_bson_entry_header(name, 0x10 );
16143 write_number<std::int32_t>(
static_cast<std::int32_t
>(j.m_data.m_value.number_unsigned),
true);
16145 else if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int64_t>::max)()))
16147 write_bson_entry_header(name, 0x12 );
16148 write_number<std::int64_t>(
static_cast<std::int64_t
>(j.m_data.m_value.number_unsigned),
true);
16152 JSON_THROW(out_of_range::create(407, concat(
"integer number ", std::to_string(j.m_data.m_value.number_unsigned),
" cannot be represented by BSON as it does not fit int64"), &j));
16160 const typename BasicJsonType::object_t& value)
16162 write_bson_entry_header(name, 0x03);
16163 write_bson_object(
value);
16171 std::size_t array_index = 0ul;
16173 const std::size_t embedded_document_size = std::accumulate(std::begin(
value), std::end(
value),
static_cast<std::size_t
>(0), [&array_index](std::size_t result,
const typename BasicJsonType::array_t::value_type & el)
16175 return result + calc_bson_element_size(std::to_string(array_index++), el);
16178 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16186 return sizeof(std::int32_t) +
value.size() + 1ul;
16193 const typename BasicJsonType::array_t& value)
16195 write_bson_entry_header(name, 0x04);
16196 write_number<std::int32_t>(
static_cast<std::int32_t
>(calc_bson_array_size(
value)),
true);
16198 std::size_t array_index = 0ul;
16200 for (
const auto& el :
value)
16202 write_bson_element(std::to_string(array_index++), el);
16205 oa->write_character(to_char_type(0x00));
16212 const binary_t& value)
16214 write_bson_entry_header(name, 0x05);
16216 write_number<std::int32_t>(
static_cast<std::int32_t
>(
value.size()),
true);
16217 write_number(
value.has_subtype() ?
static_cast<std::uint8_t
>(
value.subtype()) :
static_cast<std::uint8_t
>(0x00));
16219 oa->write_characters(
reinterpret_cast<const CharType*
>(
value.data()),
value.size());
16227 const BasicJsonType& j)
16229 const auto header_size = calc_bson_entry_header_size(name, j);
16232 case value_t::object:
16233 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16235 case value_t::array:
16236 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16238 case value_t::binary:
16239 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16241 case value_t::boolean:
16242 return header_size + 1ul;
16244 case value_t::number_float:
16245 return header_size + 8ul;
16247 case value_t::number_integer:
16248 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16250 case value_t::number_unsigned:
16251 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16253 case value_t::string:
16254 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16256 case value_t::null:
16257 return header_size + 0ul;
16260 case value_t::discarded:
16262 JSON_ASSERT(
false);
16275 const BasicJsonType& j)
16279 case value_t::object:
16280 return write_bson_object_entry(name, *j.m_data.m_value.object);
16282 case value_t::array:
16283 return write_bson_array(name, *j.m_data.m_value.array);
16285 case value_t::binary:
16286 return write_bson_binary(name, *j.m_data.m_value.binary);
16288 case value_t::boolean:
16289 return write_bson_boolean(name, j.m_data.m_value.boolean);
16291 case value_t::number_float:
16292 return write_bson_double(name, j.m_data.m_value.number_float);
16294 case value_t::number_integer:
16295 return write_bson_integer(name, j.m_data.m_value.number_integer);
16297 case value_t::number_unsigned:
16298 return write_bson_unsigned(name, j);
16300 case value_t::string:
16301 return write_bson_string(name, *j.m_data.m_value.string);
16303 case value_t::null:
16304 return write_bson_null(name);
16307 case value_t::discarded:
16309 JSON_ASSERT(
false);
16323 const std::size_t document_size = std::accumulate(
value.begin(),
value.end(),
static_cast<std::size_t
>(0),
16324 [](
size_t result,
const typename BasicJsonType::object_t::value_type & el)
16326 return result += calc_bson_element_size(el.first, el.second);
16329 return sizeof(std::int32_t) + document_size + 1ul;
16338 write_number<std::int32_t>(
static_cast<std::int32_t
>(calc_bson_object_size(
value)),
true);
16340 for (
const auto& el :
value)
16342 write_bson_element(el.first, el.second);
16345 oa->write_character(to_char_type(0x00));
16352 static constexpr CharType get_cbor_float_prefix(
float )
16354 return to_char_type(0xFA);
16357 static constexpr CharType get_cbor_float_prefix(
double )
16359 return to_char_type(0xFB);
16366 static constexpr CharType get_msgpack_float_prefix(
float )
16368 return to_char_type(0xCA);
16371 static constexpr CharType get_msgpack_float_prefix(
double )
16373 return to_char_type(0xCB);
16381 template<
typename NumberType,
typename std::enable_if<
16382 std::is_floating_point<NumberType>::value,
int>::type = 0>
16383 void write_number_with_ubjson_prefix(
const NumberType n,
16384 const bool add_prefix,
16385 const bool use_bjdata)
16389 oa->write_character(get_ubjson_float_prefix(n));
16391 write_number(n, use_bjdata);
16395 template<
typename NumberType,
typename std::enable_if<
16396 std::is_unsigned<NumberType>::value,
int>::type = 0>
16397 void write_number_with_ubjson_prefix(
const NumberType n,
16398 const bool add_prefix,
16399 const bool use_bjdata)
16401 if (n <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int8_t>::max)()))
16405 oa->write_character(to_char_type(
'i'));
16407 write_number(
static_cast<std::uint8_t
>(n), use_bjdata);
16409 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16413 oa->write_character(to_char_type(
'U'));
16415 write_number(
static_cast<std::uint8_t
>(n), use_bjdata);
16417 else if (n <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int16_t>::max)()))
16421 oa->write_character(to_char_type(
'I'));
16423 write_number(
static_cast<std::int16_t
>(n), use_bjdata);
16425 else if (use_bjdata && n <=
static_cast<uint64_t
>((std::numeric_limits<uint16_t>::max)()))
16429 oa->write_character(to_char_type(
'u'));
16431 write_number(
static_cast<std::uint16_t
>(n), use_bjdata);
16433 else if (n <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int32_t>::max)()))
16437 oa->write_character(to_char_type(
'l'));
16439 write_number(
static_cast<std::int32_t
>(n), use_bjdata);
16441 else if (use_bjdata && n <=
static_cast<uint64_t
>((std::numeric_limits<uint32_t>::max)()))
16445 oa->write_character(to_char_type(
'm'));
16447 write_number(
static_cast<std::uint32_t
>(n), use_bjdata);
16449 else if (n <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int64_t>::max)()))
16453 oa->write_character(to_char_type(
'L'));
16455 write_number(
static_cast<std::int64_t
>(n), use_bjdata);
16457 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16461 oa->write_character(to_char_type(
'M'));
16463 write_number(
static_cast<std::uint64_t
>(n), use_bjdata);
16469 oa->write_character(to_char_type(
'H'));
16472 const auto number = BasicJsonType(n).dump();
16473 write_number_with_ubjson_prefix(number.size(),
true, use_bjdata);
16474 for (std::size_t i = 0; i < number.size(); ++i)
16476 oa->write_character(to_char_type(
static_cast<std::uint8_t
>(number[i])));
16482 template <
typename NumberType,
typename std::enable_if <
16483 std::is_signed<NumberType>::value&&
16484 !std::is_floating_point<NumberType>::value,
int >::type = 0 >
16485 void write_number_with_ubjson_prefix(
const NumberType n,
16486 const bool add_prefix,
16487 const bool use_bjdata)
16489 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16493 oa->write_character(to_char_type(
'i'));
16495 write_number(
static_cast<std::int8_t
>(n), use_bjdata);
16497 else if (
static_cast<std::int64_t
>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <=
static_cast<std::int64_t
>((std::numeric_limits<std::uint8_t>::max)()))
16501 oa->write_character(to_char_type(
'U'));
16503 write_number(
static_cast<std::uint8_t
>(n), use_bjdata);
16505 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16509 oa->write_character(to_char_type(
'I'));
16511 write_number(
static_cast<std::int16_t
>(n), use_bjdata);
16513 else if (use_bjdata && (
static_cast<std::int64_t
>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <=
static_cast<std::int64_t
>((std::numeric_limits<std::uint16_t>::max)())))
16517 oa->write_character(to_char_type(
'u'));
16519 write_number(
static_cast<uint16_t
>(n), use_bjdata);
16521 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16525 oa->write_character(to_char_type(
'l'));
16527 write_number(
static_cast<std::int32_t
>(n), use_bjdata);
16529 else if (use_bjdata && (
static_cast<std::int64_t
>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <=
static_cast<std::int64_t
>((std::numeric_limits<std::uint32_t>::max)())))
16533 oa->write_character(to_char_type(
'm'));
16535 write_number(
static_cast<uint32_t
>(n), use_bjdata);
16537 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16541 oa->write_character(to_char_type(
'L'));
16543 write_number(
static_cast<std::int64_t
>(n), use_bjdata);
16550 oa->write_character(to_char_type(
'H'));
16553 const auto number = BasicJsonType(n).dump();
16554 write_number_with_ubjson_prefix(number.size(),
true, use_bjdata);
16555 for (std::size_t i = 0; i < number.size(); ++i)
16557 oa->write_character(to_char_type(
static_cast<std::uint8_t
>(number[i])));
16566 CharType
ubjson_prefix(
const BasicJsonType& j,
const bool use_bjdata)
const noexcept
16570 case value_t::null:
16573 case value_t::boolean:
16574 return j.m_data.m_value.boolean ?
'T' :
'F';
16576 case value_t::number_integer:
16578 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16582 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
16586 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16590 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
16594 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16598 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
16602 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16610 case value_t::number_unsigned:
16612 if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int8_t>::max)()))
16616 if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::uint8_t>::max)()))
16620 if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int16_t>::max)()))
16624 if (use_bjdata && j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::uint16_t>::max)()))
16628 if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int32_t>::max)()))
16632 if (use_bjdata && j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::uint32_t>::max)()))
16636 if (j.m_data.m_value.number_unsigned <=
static_cast<std::uint64_t
>((std::numeric_limits<std::int64_t>::max)()))
16640 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16648 case value_t::number_float:
16649 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16651 case value_t::string:
16654 case value_t::array:
16655 case value_t::binary:
16658 case value_t::object:
16661 case value_t::discarded:
16667 static constexpr CharType get_ubjson_float_prefix(
float )
16672 static constexpr CharType get_ubjson_float_prefix(
double )
16682 std::map<string_t, CharType> bjdtype = {{
"uint8",
'U'}, {
"int8",
'i'}, {
"uint16",
'u'}, {
"int16",
'I'},
16683 {
"uint32",
'm'}, {
"int32",
'l'}, {
"uint64",
'M'}, {
"int64",
'L'}, {
"single",
'd'}, {
"double",
'D'}, {
"char",
'C'}
16686 string_t
key =
"_ArrayType_";
16687 auto it = bjdtype.find(
static_cast<string_t
>(
value.at(
key)));
16688 if (it == bjdtype.end())
16692 CharType dtype = it->second;
16694 key =
"_ArraySize_";
16695 std::size_t len = (
value.at(
key).empty() ? 0 : 1);
16696 for (
const auto& el :
value.at(
key))
16698 len *=
static_cast<std::size_t
>(el.m_data.m_value.number_unsigned);
16701 key =
"_ArrayData_";
16707 oa->write_character(
'[');
16708 oa->write_character(
'$');
16709 oa->write_character(dtype);
16710 oa->write_character(
'#');
16712 key =
"_ArraySize_";
16713 write_ubjson(
value.at(
key), use_count, use_type,
true,
true);
16715 key =
"_ArrayData_";
16716 if (dtype ==
'U' || dtype ==
'C')
16718 for (
const auto& el :
value.at(
key))
16720 write_number(
static_cast<std::uint8_t
>(el.m_data.m_value.number_unsigned),
true);
16723 else if (dtype ==
'i')
16725 for (
const auto& el :
value.at(
key))
16727 write_number(
static_cast<std::int8_t
>(el.m_data.m_value.number_integer),
true);
16730 else if (dtype ==
'u')
16732 for (
const auto& el :
value.at(
key))
16734 write_number(
static_cast<std::uint16_t
>(el.m_data.m_value.number_unsigned),
true);
16737 else if (dtype ==
'I')
16739 for (
const auto& el :
value.at(
key))
16741 write_number(
static_cast<std::int16_t
>(el.m_data.m_value.number_integer),
true);
16744 else if (dtype ==
'm')
16746 for (
const auto& el :
value.at(
key))
16748 write_number(
static_cast<std::uint32_t
>(el.m_data.m_value.number_unsigned),
true);
16751 else if (dtype ==
'l')
16753 for (
const auto& el :
value.at(
key))
16755 write_number(
static_cast<std::int32_t
>(el.m_data.m_value.number_integer),
true);
16758 else if (dtype ==
'M')
16760 for (
const auto& el :
value.at(
key))
16762 write_number(
static_cast<std::uint64_t
>(el.m_data.m_value.number_unsigned),
true);
16765 else if (dtype ==
'L')
16767 for (
const auto& el :
value.at(
key))
16769 write_number(
static_cast<std::int64_t
>(el.m_data.m_value.number_integer),
true);
16772 else if (dtype ==
'd')
16774 for (
const auto& el :
value.at(
key))
16776 write_number(
static_cast<float>(el.m_data.m_value.number_float),
true);
16779 else if (dtype ==
'D')
16781 for (
const auto& el :
value.at(
key))
16783 write_number(
static_cast<double>(el.m_data.m_value.number_float),
true);
16806 template<
typename NumberType>
16807 void write_number(
const NumberType n,
const bool OutputIsLittleEndian =
false)
16810 std::array<CharType,
sizeof(NumberType)> vec{};
16811 std::memcpy(vec.data(), &n,
sizeof(NumberType));
16814 if (is_little_endian != OutputIsLittleEndian)
16817 std::reverse(vec.begin(), vec.end());
16820 oa->write_characters(vec.data(),
sizeof(NumberType));
16826#pragma GCC diagnostic push
16827#pragma GCC diagnostic ignored "-Wfloat-equal"
16829 if (
static_cast<double>(n) >=
static_cast<double>(std::numeric_limits<float>::lowest()) &&
16830 static_cast<double>(n) <=
static_cast<double>((std::numeric_limits<float>::max)()) &&
16831 static_cast<double>(
static_cast<float>(n)) ==
static_cast<double>(n))
16833 oa->write_character(format == detail::input_format_t::cbor
16834 ? get_cbor_float_prefix(
static_cast<float>(n))
16835 : get_msgpack_float_prefix(static_cast<float>(n)));
16836 write_number(
static_cast<float>(n));
16840 oa->write_character(format == detail::input_format_t::cbor
16841 ? get_cbor_float_prefix(n)
16842 : get_msgpack_float_prefix(n));
16846#pragma GCC diagnostic pop
16855 template <
typename C = CharType,
16856 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * =
nullptr >
16857 static constexpr CharType to_char_type(std::uint8_t x)
noexcept
16859 return *
reinterpret_cast<char*
>(&x);
16862 template <
typename C = CharType,
16863 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * =
nullptr >
16864 static CharType to_char_type(std::uint8_t x)
noexcept
16866 static_assert(
sizeof(std::uint8_t) ==
sizeof(CharType),
"size of CharType must be equal to std::uint8_t");
16867 static_assert(std::is_trivial<CharType>::value,
"CharType must be trivial");
16869 std::memcpy(&result, &x,
sizeof(x));
16873 template<
typename C = CharType,
16874 enable_if_t<std::is_unsigned<C>::value>* =
nullptr>
16875 static constexpr CharType to_char_type(std::uint8_t x)
noexcept
16880 template <
typename InputCharType,
typename C = CharType,
16882 std::is_signed<C>::value &&
16883 std::is_signed<char>::value &&
16884 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16886 static constexpr CharType to_char_type(InputCharType x)
noexcept
16900NLOHMANN_JSON_NAMESPACE_END
16916#include <algorithm>
16926#include <type_traits>
16946#include <type_traits>
16951NLOHMANN_JSON_NAMESPACE_BEGIN
16977template<
typename Target,
typename Source>
16978Target reinterpret_bits(
const Source source)
16980 static_assert(
sizeof(Target) ==
sizeof(Source),
"size mismatch");
16983 std::memcpy(&target, &source,
sizeof(Source));
16989 static constexpr int kPrecision = 64;
16991 std::uint64_t f = 0;
16994 constexpr diyfp(std::uint64_t f_,
int e_) noexcept : f(f_), e(e_) {}
17002 JSON_ASSERT(x.e == y.e);
17003 JSON_ASSERT(x.f >= y.f);
17005 return {x.f - y.f, x.e};
17014 static_assert(kPrecision == 64,
"internal error");
17039 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17040 const std::uint64_t u_hi = x.f >> 32u;
17041 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17042 const std::uint64_t v_hi = y.f >> 32u;
17044 const std::uint64_t p0 = u_lo * v_lo;
17045 const std::uint64_t p1 = u_lo * v_hi;
17046 const std::uint64_t p2 = u_hi * v_lo;
17047 const std::uint64_t p3 = u_hi * v_hi;
17049 const std::uint64_t p0_hi = p0 >> 32u;
17050 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17051 const std::uint64_t p1_hi = p1 >> 32u;
17052 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17053 const std::uint64_t p2_hi = p2 >> 32u;
17055 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17066 Q += std::uint64_t{1} << (64u - 32u - 1u);
17068 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17070 return {h, x.e + y.e + 64};
17079 JSON_ASSERT(x.f != 0);
17081 while ((x.f >> 63u) == 0)
17096 const int delta = x.e - target_exponent;
17098 JSON_ASSERT(delta >= 0);
17099 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17101 return {x.f << delta, target_exponent};
17118template<
typename FloatType>
17121 JSON_ASSERT(std::isfinite(
value));
17122 JSON_ASSERT(
value > 0);
17131 static_assert(std::numeric_limits<FloatType>::is_iec559,
17132 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17134 constexpr int kPrecision = std::numeric_limits<FloatType>::digits;
17135 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17136 constexpr int kMinExp = 1 - kBias;
17137 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1);
17139 using bits_type =
typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17141 const auto bits =
static_cast<std::uint64_t
>(reinterpret_bits<bits_type>(
value));
17142 const std::uint64_t E = bits >> (kPrecision - 1);
17143 const std::uint64_t F = bits & (kHiddenBit - 1);
17145 const bool is_denormal = E == 0;
17146 const diyfp v = is_denormal
17147 ?
diyfp(F, kMinExp)
17148 :
diyfp(F + kHiddenBit,
static_cast<int>(E) - kBias);
17171 const bool lower_boundary_is_closer = F == 0 && E > 1;
17172 const diyfp m_plus =
diyfp(2 * v.f + 1, v.e - 1);
17173 const diyfp m_minus = lower_boundary_is_closer
17174 ?
diyfp(4 * v.f - 1, v.e - 2)
17175 :
diyfp(2 * v.f - 1, v.e - 1);
17178 const diyfp w_plus = diyfp::normalize(m_plus);
17181 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17183 return {diyfp::normalize(v), w_minus, w_plus};
17241constexpr int kAlpha = -60;
17242constexpr int kGamma = -32;
17310 constexpr int kCachedPowersMinDecExp = -300;
17311 constexpr int kCachedPowersDecStep = 8;
17313 static constexpr std::array<cached_power, 79> kCachedPowers =
17316 { 0xAB70FE17C79AC6CA, -1060, -300 },
17317 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17318 { 0xBE5691EF416BD60C, -1007, -284 },
17319 { 0x8DD01FAD907FFC3C, -980, -276 },
17320 { 0xD3515C2831559A83, -954, -268 },
17321 { 0x9D71AC8FADA6C9B5, -927, -260 },
17322 { 0xEA9C227723EE8BCB, -901, -252 },
17323 { 0xAECC49914078536D, -874, -244 },
17324 { 0x823C12795DB6CE57, -847, -236 },
17325 { 0xC21094364DFB5637, -821, -228 },
17326 { 0x9096EA6F3848984F, -794, -220 },
17327 { 0xD77485CB25823AC7, -768, -212 },
17328 { 0xA086CFCD97BF97F4, -741, -204 },
17329 { 0xEF340A98172AACE5, -715, -196 },
17330 { 0xB23867FB2A35B28E, -688, -188 },
17331 { 0x84C8D4DFD2C63F3B, -661, -180 },
17332 { 0xC5DD44271AD3CDBA, -635, -172 },
17333 { 0x936B9FCEBB25C996, -608, -164 },
17334 { 0xDBAC6C247D62A584, -582, -156 },
17335 { 0xA3AB66580D5FDAF6, -555, -148 },
17336 { 0xF3E2F893DEC3F126, -529, -140 },
17337 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17338 { 0x87625F056C7C4A8B, -475, -124 },
17339 { 0xC9BCFF6034C13053, -449, -116 },
17340 { 0x964E858C91BA2655, -422, -108 },
17341 { 0xDFF9772470297EBD, -396, -100 },
17342 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17343 { 0xF8A95FCF88747D94, -343, -84 },
17344 { 0xB94470938FA89BCF, -316, -76 },
17345 { 0x8A08F0F8BF0F156B, -289, -68 },
17346 { 0xCDB02555653131B6, -263, -60 },
17347 { 0x993FE2C6D07B7FAC, -236, -52 },
17348 { 0xE45C10C42A2B3B06, -210, -44 },
17349 { 0xAA242499697392D3, -183, -36 },
17350 { 0xFD87B5F28300CA0E, -157, -28 },
17351 { 0xBCE5086492111AEB, -130, -20 },
17352 { 0x8CBCCC096F5088CC, -103, -12 },
17353 { 0xD1B71758E219652C, -77, -4 },
17354 { 0x9C40000000000000, -50, 4 },
17355 { 0xE8D4A51000000000, -24, 12 },
17356 { 0xAD78EBC5AC620000, 3, 20 },
17357 { 0x813F3978F8940984, 30, 28 },
17358 { 0xC097CE7BC90715B3, 56, 36 },
17359 { 0x8F7E32CE7BEA5C70, 83, 44 },
17360 { 0xD5D238A4ABE98068, 109, 52 },
17361 { 0x9F4F2726179A2245, 136, 60 },
17362 { 0xED63A231D4C4FB27, 162, 68 },
17363 { 0xB0DE65388CC8ADA8, 189, 76 },
17364 { 0x83C7088E1AAB65DB, 216, 84 },
17365 { 0xC45D1DF942711D9A, 242, 92 },
17366 { 0x924D692CA61BE758, 269, 100 },
17367 { 0xDA01EE641A708DEA, 295, 108 },
17368 { 0xA26DA3999AEF774A, 322, 116 },
17369 { 0xF209787BB47D6B85, 348, 124 },
17370 { 0xB454E4A179DD1877, 375, 132 },
17371 { 0x865B86925B9BC5C2, 402, 140 },
17372 { 0xC83553C5C8965D3D, 428, 148 },
17373 { 0x952AB45CFA97A0B3, 455, 156 },
17374 { 0xDE469FBD99A05FE3, 481, 164 },
17375 { 0xA59BC234DB398C25, 508, 172 },
17376 { 0xF6C69A72A3989F5C, 534, 180 },
17377 { 0xB7DCBF5354E9BECE, 561, 188 },
17378 { 0x88FCF317F22241E2, 588, 196 },
17379 { 0xCC20CE9BD35C78A5, 614, 204 },
17380 { 0x98165AF37B2153DF, 641, 212 },
17381 { 0xE2A0B5DC971F303A, 667, 220 },
17382 { 0xA8D9D1535CE3B396, 694, 228 },
17383 { 0xFB9B7CD9A4A7443C, 720, 236 },
17384 { 0xBB764C4CA7A44410, 747, 244 },
17385 { 0x8BAB8EEFB6409C1A, 774, 252 },
17386 { 0xD01FEF10A657842C, 800, 260 },
17387 { 0x9B10A4E5E9913129, 827, 268 },
17388 { 0xE7109BFBA19C0C9D, 853, 276 },
17389 { 0xAC2820D9623BF429, 880, 284 },
17390 { 0x80444B5E7AA7CF85, 907, 292 },
17391 { 0xBF21E44003ACDD2D, 933, 300 },
17392 { 0x8E679C2F5E44FF8F, 960, 308 },
17393 { 0xD433179D9C8CB841, 986, 316 },
17394 { 0x9E19DB92B4E31BA9, 1013, 324 },
17402 JSON_ASSERT(e >= -1500);
17403 JSON_ASSERT(e <= 1500);
17404 const int f = kAlpha - e - 1;
17405 const int k = (f * 78913) / (1 << 18) +
static_cast<int>(f > 0);
17407 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17408 JSON_ASSERT(index >= 0);
17409 JSON_ASSERT(
static_cast<std::size_t
>(index) < kCachedPowers.size());
17411 const cached_power cached = kCachedPowers[
static_cast<std::size_t
>(index)];
17412 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17413 JSON_ASSERT(kGamma >= cached.e + e + 64);
17425 if (n >= 1000000000)
17427 pow10 = 1000000000;
17431 if (n >= 100000000)
17476inline void grisu2_round(
char* buf,
int len, std::uint64_t dist, std::uint64_t delta,
17477 std::uint64_t rest, std::uint64_t ten_k)
17479 JSON_ASSERT(len >= 1);
17480 JSON_ASSERT(dist <= delta);
17481 JSON_ASSERT(rest <= delta);
17482 JSON_ASSERT(ten_k > 0);
17504 && delta - rest >= ten_k
17505 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17507 JSON_ASSERT(buf[len - 1] !=
'0');
17520 static_assert(kAlpha >= -60,
"internal error");
17521 static_assert(kGamma <= -32,
"internal error");
17535 JSON_ASSERT(M_plus.e >= kAlpha);
17536 JSON_ASSERT(M_plus.e <= kGamma);
17538 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f;
17539 std::uint64_t dist = diyfp::sub(M_plus, w ).f;
17548 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17550 auto p1 =
static_cast<std::uint32_t
>(M_plus.f >> -one.e);
17551 std::uint64_t p2 = M_plus.f & (one.f - 1);
17557 JSON_ASSERT(p1 > 0);
17559 std::uint32_t pow10{};
17587 const std::uint32_t d = p1 / pow10;
17588 const std::uint32_t r = p1 % pow10;
17593 JSON_ASSERT(d <= 9);
17594 buffer[length++] =
static_cast<char>(
'0' + d);
17613 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17618 decimal_exponent += n;
17629 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17630 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17680 JSON_ASSERT(p2 > delta);
17691 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17693 const std::uint64_t d = p2 >> -one.e;
17694 const std::uint64_t r = p2 & (one.f - 1);
17700 JSON_ASSERT(d <= 9);
17701 buffer[length++] =
static_cast<char>(
'0' + d);
17726 decimal_exponent -= m;
17734 const std::uint64_t ten_m = one.f;
17735 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17757JSON_HEDLEY_NON_NULL(1)
17758inline
void grisu2(
char* buf,
int& len,
int& decimal_exponent,
17761 JSON_ASSERT(m_plus.e == m_minus.e);
17762 JSON_ASSERT(m_plus.e == v.e);
17775 const diyfp c_minus_k(cached.f, cached.e);
17778 const diyfp w = diyfp::mul(v, c_minus_k);
17779 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17780 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17803 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17804 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17806 decimal_exponent = -cached.k;
17816template<
typename FloatType>
17817JSON_HEDLEY_NON_NULL(1)
17818void grisu2(
char* buf,
int& len,
int& decimal_exponent, FloatType value)
17820 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17821 "internal error: not enough precision");
17823 JSON_ASSERT(std::isfinite(
value));
17824 JSON_ASSERT(
value > 0);
17848 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17856JSON_HEDLEY_NON_NULL(1)
17857JSON_HEDLEY_RETURNS_NON_NULL
17858inline
char* append_exponent(
char* buf,
int e)
17860 JSON_ASSERT(e > -1000);
17861 JSON_ASSERT(e < 1000);
17873 auto k =
static_cast<std::uint32_t
>(e);
17879 *buf++ =
static_cast<char>(
'0' + k);
17883 *buf++ =
static_cast<char>(
'0' + k / 10);
17885 *buf++ =
static_cast<char>(
'0' + k);
17889 *buf++ =
static_cast<char>(
'0' + k / 100);
17891 *buf++ =
static_cast<char>(
'0' + k / 10);
17893 *buf++ =
static_cast<char>(
'0' + k);
17908JSON_HEDLEY_NON_NULL(1)
17909JSON_HEDLEY_RETURNS_NON_NULL
17910inline
char* format_buffer(
char* buf,
int len,
int decimal_exponent,
17911 int min_exp,
int max_exp)
17913 JSON_ASSERT(min_exp < 0);
17914 JSON_ASSERT(max_exp > 0);
17917 const int n = len + decimal_exponent;
17923 if (k <= n && n <= max_exp)
17928 std::memset(buf + k,
'0',
static_cast<size_t>(n) -
static_cast<size_t>(k));
17932 return buf + (
static_cast<size_t>(n) + 2);
17935 if (0 < n && n <= max_exp)
17940 JSON_ASSERT(k > n);
17942 std::memmove(buf + (
static_cast<size_t>(n) + 1), buf + n,
static_cast<size_t>(k) -
static_cast<size_t>(n));
17944 return buf + (
static_cast<size_t>(k) + 1U);
17947 if (min_exp < n && n <= 0)
17952 std::memmove(buf + (2 +
static_cast<size_t>(-n)), buf,
static_cast<size_t>(k));
17955 std::memset(buf + 2,
'0',
static_cast<size_t>(-n));
17956 return buf + (2U +
static_cast<size_t>(-n) +
static_cast<size_t>(k));
17971 std::memmove(buf + 2, buf + 1,
static_cast<size_t>(k) - 1);
17973 buf += 1 +
static_cast<size_t>(k);
17992template<
typename FloatType>
17993JSON_HEDLEY_NON_NULL(1, 2)
17994JSON_HEDLEY_RETURNS_NON_NULL
17995char* to_chars(
char* first, const
char* last, FloatType value)
17997 static_cast<void>(last);
17998 JSON_ASSERT(std::isfinite(
value));
18001 if (std::signbit(
value))
18008#pragma GCC diagnostic push
18009#pragma GCC diagnostic ignored "-Wfloat-equal"
18020#pragma GCC diagnostic pop
18023 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18030 int decimal_exponent = 0;
18031 dtoa_impl::grisu2(first, len, decimal_exponent,
value);
18033 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18036 constexpr int kMinExp = -4;
18038 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18040 JSON_ASSERT(last - first >= kMaxExp + 2);
18041 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18042 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18044 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18048NLOHMANN_JSON_NAMESPACE_END
18065NLOHMANN_JSON_NAMESPACE_BEGIN
18081template<
typename BasicJsonType>
18084 using string_t =
typename BasicJsonType::string_t;
18085 using number_float_t =
typename BasicJsonType::number_float_t;
18086 using number_integer_t =
typename BasicJsonType::number_integer_t;
18087 using number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
18088 using binary_char_t =
typename BasicJsonType::binary_t::value_type;
18089 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18090 static constexpr std::uint8_t UTF8_REJECT = 1;
18101 , loc(std::localeconv())
18102 , thousands_sep(loc->thousands_sep == nullptr ?
'\0' : std::
char_traits<char>::to_char_type(* (loc->thousands_sep)))
18103 , decimal_point(loc->decimal_point == nullptr ?
'\0' : std::
char_traits<char>::to_char_type(* (loc->decimal_point)))
18104 , indent_char(ichar)
18105 , indent_string(512, indent_char)
18106 , error_handler(error_handler_)
18139 const bool pretty_print,
18140 const bool ensure_ascii,
18141 const unsigned int indent_step,
18142 const unsigned int current_indent = 0)
18144 switch (val.m_data.m_type)
18146 case value_t::object:
18148 if (val.m_data.m_value.object->empty())
18150 o->write_characters(
"{}", 2);
18156 o->write_characters(
"{\n", 2);
18159 const auto new_indent = current_indent + indent_step;
18160 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18162 indent_string.resize(indent_string.size() * 2,
' ');
18166 auto i = val.m_data.m_value.object->cbegin();
18167 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18169 o->write_characters(indent_string.c_str(), new_indent);
18170 o->write_character(
'\"');
18171 dump_escaped(i->first, ensure_ascii);
18172 o->write_characters(
"\": ", 3);
18173 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
18174 o->write_characters(
",\n", 2);
18178 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18179 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18180 o->write_characters(indent_string.c_str(), new_indent);
18181 o->write_character(
'\"');
18182 dump_escaped(i->first, ensure_ascii);
18183 o->write_characters(
"\": ", 3);
18184 dump(i->second,
true, ensure_ascii, indent_step, new_indent);
18186 o->write_character(
'\n');
18187 o->write_characters(indent_string.c_str(), current_indent);
18188 o->write_character(
'}');
18192 o->write_character(
'{');
18195 auto i = val.m_data.m_value.object->cbegin();
18196 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18198 o->write_character(
'\"');
18199 dump_escaped(i->first, ensure_ascii);
18200 o->write_characters(
"\":", 2);
18201 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
18202 o->write_character(
',');
18206 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18207 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18208 o->write_character(
'\"');
18209 dump_escaped(i->first, ensure_ascii);
18210 o->write_characters(
"\":", 2);
18211 dump(i->second,
false, ensure_ascii, indent_step, current_indent);
18213 o->write_character(
'}');
18219 case value_t::array:
18221 if (val.m_data.m_value.array->empty())
18223 o->write_characters(
"[]", 2);
18229 o->write_characters(
"[\n", 2);
18232 const auto new_indent = current_indent + indent_step;
18233 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18235 indent_string.resize(indent_string.size() * 2,
' ');
18239 for (
auto i = val.m_data.m_value.array->cbegin();
18240 i != val.m_data.m_value.array->cend() - 1; ++i)
18242 o->write_characters(indent_string.c_str(), new_indent);
18243 dump(*i,
true, ensure_ascii, indent_step, new_indent);
18244 o->write_characters(
",\n", 2);
18248 JSON_ASSERT(!val.m_data.m_value.array->empty());
18249 o->write_characters(indent_string.c_str(), new_indent);
18250 dump(val.m_data.m_value.array->back(),
true, ensure_ascii, indent_step, new_indent);
18252 o->write_character(
'\n');
18253 o->write_characters(indent_string.c_str(), current_indent);
18254 o->write_character(
']');
18258 o->write_character(
'[');
18261 for (
auto i = val.m_data.m_value.array->cbegin();
18262 i != val.m_data.m_value.array->cend() - 1; ++i)
18264 dump(*i,
false, ensure_ascii, indent_step, current_indent);
18265 o->write_character(
',');
18269 JSON_ASSERT(!val.m_data.m_value.array->empty());
18270 dump(val.m_data.m_value.array->back(),
false, ensure_ascii, indent_step, current_indent);
18272 o->write_character(
']');
18278 case value_t::string:
18280 o->write_character(
'\"');
18281 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18282 o->write_character(
'\"');
18286 case value_t::binary:
18290 o->write_characters(
"{\n", 2);
18293 const auto new_indent = current_indent + indent_step;
18294 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18296 indent_string.resize(indent_string.size() * 2,
' ');
18299 o->write_characters(indent_string.c_str(), new_indent);
18301 o->write_characters(
"\"bytes\": [", 10);
18303 if (!val.m_data.m_value.binary->empty())
18305 for (
auto i = val.m_data.m_value.binary->cbegin();
18306 i != val.m_data.m_value.binary->cend() - 1; ++i)
18309 o->write_characters(
", ", 2);
18311 dump_integer(val.m_data.m_value.binary->back());
18314 o->write_characters(
"],\n", 3);
18315 o->write_characters(indent_string.c_str(), new_indent);
18317 o->write_characters(
"\"subtype\": ", 11);
18318 if (val.m_data.m_value.binary->has_subtype())
18320 dump_integer(val.m_data.m_value.binary->subtype());
18324 o->write_characters(
"null", 4);
18326 o->write_character(
'\n');
18327 o->write_characters(indent_string.c_str(), current_indent);
18328 o->write_character(
'}');
18332 o->write_characters(
"{\"bytes\":[", 10);
18334 if (!val.m_data.m_value.binary->empty())
18336 for (
auto i = val.m_data.m_value.binary->cbegin();
18337 i != val.m_data.m_value.binary->cend() - 1; ++i)
18340 o->write_character(
',');
18342 dump_integer(val.m_data.m_value.binary->back());
18345 o->write_characters(
"],\"subtype\":", 12);
18346 if (val.m_data.m_value.binary->has_subtype())
18348 dump_integer(val.m_data.m_value.binary->subtype());
18349 o->write_character(
'}');
18353 o->write_characters(
"null}", 5);
18359 case value_t::boolean:
18361 if (val.m_data.m_value.boolean)
18363 o->write_characters(
"true", 4);
18367 o->write_characters(
"false", 5);
18372 case value_t::number_integer:
18374 dump_integer(val.m_data.m_value.number_integer);
18378 case value_t::number_unsigned:
18380 dump_integer(val.m_data.m_value.number_unsigned);
18384 case value_t::number_float:
18386 dump_float(val.m_data.m_value.number_float);
18390 case value_t::discarded:
18392 o->write_characters(
"<discarded>", 11);
18396 case value_t::null:
18398 o->write_characters(
"null", 4);
18403 JSON_ASSERT(
false);
18407 JSON_PRIVATE_UNLESS_TESTED:
18422 void dump_escaped(
const string_t& s,
const bool ensure_ascii)
18424 std::uint32_t codepoint{};
18425 std::uint8_t state = UTF8_ACCEPT;
18426 std::size_t bytes = 0;
18429 std::size_t bytes_after_last_accept = 0;
18430 std::size_t undumped_chars = 0;
18432 for (std::size_t i = 0; i < s.size(); ++i)
18434 const auto byte =
static_cast<std::uint8_t
>(s[i]);
18436 switch (decode(state, codepoint,
byte))
18444 string_buffer[bytes++] =
'\\';
18445 string_buffer[bytes++] =
'b';
18451 string_buffer[bytes++] =
'\\';
18452 string_buffer[bytes++] =
't';
18458 string_buffer[bytes++] =
'\\';
18459 string_buffer[bytes++] =
'n';
18465 string_buffer[bytes++] =
'\\';
18466 string_buffer[bytes++] =
'f';
18472 string_buffer[bytes++] =
'\\';
18473 string_buffer[bytes++] =
'r';
18479 string_buffer[bytes++] =
'\\';
18480 string_buffer[bytes++] =
'\"';
18486 string_buffer[bytes++] =
'\\';
18487 string_buffer[bytes++] =
'\\';
18495 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18497 if (codepoint <= 0xFFFF)
18500 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7,
"\\u%04x",
18501 static_cast<std::uint16_t
>(codepoint)));
18507 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13,
"\\u%04x\\u%04x",
18508 static_cast<std::uint16_t
>(0xD7C0u + (codepoint >> 10u)),
18509 static_cast<std::uint16_t
>(0xDC00u + (codepoint & 0x3FFu))));
18517 string_buffer[bytes++] = s[i];
18526 if (string_buffer.size() - bytes < 13)
18528 o->write_characters(string_buffer.data(), bytes);
18533 bytes_after_last_accept = bytes;
18534 undumped_chars = 0;
18540 switch (error_handler)
18542 case error_handler_t::strict:
18544 JSON_THROW(type_error::create(316, concat(
"invalid UTF-8 byte at index ", std::to_string(i),
": 0x", hex_bytes(
byte | 0)),
nullptr));
18547 case error_handler_t::ignore:
18548 case error_handler_t::replace:
18554 if (undumped_chars > 0)
18561 bytes = bytes_after_last_accept;
18563 if (error_handler == error_handler_t::replace)
18568 string_buffer[bytes++] =
'\\';
18569 string_buffer[bytes++] =
'u';
18570 string_buffer[bytes++] =
'f';
18571 string_buffer[bytes++] =
'f';
18572 string_buffer[bytes++] =
'f';
18573 string_buffer[bytes++] =
'd';
18585 if (string_buffer.size() - bytes < 13)
18587 o->write_characters(string_buffer.data(), bytes);
18591 bytes_after_last_accept = bytes;
18594 undumped_chars = 0;
18597 state = UTF8_ACCEPT;
18602 JSON_ASSERT(
false);
18612 string_buffer[bytes++] = s[i];
18621 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18626 o->write_characters(string_buffer.data(), bytes);
18632 switch (error_handler)
18634 case error_handler_t::strict:
18636 JSON_THROW(type_error::create(316, concat(
"incomplete UTF-8 string; last byte: 0x", hex_bytes(
static_cast<std::uint8_t
>(s.back() | 0))),
nullptr));
18639 case error_handler_t::ignore:
18642 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18646 case error_handler_t::replace:
18649 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18653 o->write_characters(
"\\ufffd", 6);
18657 o->write_characters(
"\xEF\xBF\xBD", 3);
18663 JSON_ASSERT(
false);
18677 inline unsigned int count_digits(number_unsigned_t x)
noexcept
18679 unsigned int n_digits = 1;
18688 return n_digits + 1;
18692 return n_digits + 2;
18696 return n_digits + 3;
18708 static std::string hex_bytes(std::uint8_t
byte)
18710 std::string result =
"FF";
18711 constexpr const char* nibble_to_hex =
"0123456789ABCDEF";
18712 result[0] = nibble_to_hex[
byte / 16];
18713 result[1] = nibble_to_hex[
byte % 16];
18718 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value,
int> = 0>
18719 bool is_negative_number(NumberType x)
18724 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value,
int > = 0 >
18725 bool is_negative_number(NumberType )
18739 template <
typename NumberType, detail::enable_if_t <
18740 std::is_integral<NumberType>::value ||
18741 std::is_same<NumberType, number_unsigned_t>::value ||
18742 std::is_same<NumberType, number_integer_t>::value ||
18743 std::is_same<NumberType, binary_char_t>::value,
18745 void dump_integer(NumberType x)
18747 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18750 {{
'0',
'0'}}, {{
'0',
'1'}}, {{
'0',
'2'}}, {{
'0',
'3'}}, {{
'0',
'4'}}, {{
'0',
'5'}}, {{
'0',
'6'}}, {{
'0',
'7'}}, {{
'0',
'8'}}, {{
'0',
'9'}},
18751 {{
'1',
'0'}}, {{
'1',
'1'}}, {{
'1',
'2'}}, {{
'1',
'3'}}, {{
'1',
'4'}}, {{
'1',
'5'}}, {{
'1',
'6'}}, {{
'1',
'7'}}, {{
'1',
'8'}}, {{
'1',
'9'}},
18752 {{
'2',
'0'}}, {{
'2',
'1'}}, {{
'2',
'2'}}, {{
'2',
'3'}}, {{
'2',
'4'}}, {{
'2',
'5'}}, {{
'2',
'6'}}, {{
'2',
'7'}}, {{
'2',
'8'}}, {{
'2',
'9'}},
18753 {{
'3',
'0'}}, {{
'3',
'1'}}, {{
'3',
'2'}}, {{
'3',
'3'}}, {{
'3',
'4'}}, {{
'3',
'5'}}, {{
'3',
'6'}}, {{
'3',
'7'}}, {{
'3',
'8'}}, {{
'3',
'9'}},
18754 {{
'4',
'0'}}, {{
'4',
'1'}}, {{
'4',
'2'}}, {{
'4',
'3'}}, {{
'4',
'4'}}, {{
'4',
'5'}}, {{
'4',
'6'}}, {{
'4',
'7'}}, {{
'4',
'8'}}, {{
'4',
'9'}},
18755 {{
'5',
'0'}}, {{
'5',
'1'}}, {{
'5',
'2'}}, {{
'5',
'3'}}, {{
'5',
'4'}}, {{
'5',
'5'}}, {{
'5',
'6'}}, {{
'5',
'7'}}, {{
'5',
'8'}}, {{
'5',
'9'}},
18756 {{
'6',
'0'}}, {{
'6',
'1'}}, {{
'6',
'2'}}, {{
'6',
'3'}}, {{
'6',
'4'}}, {{
'6',
'5'}}, {{
'6',
'6'}}, {{
'6',
'7'}}, {{
'6',
'8'}}, {{
'6',
'9'}},
18757 {{
'7',
'0'}}, {{
'7',
'1'}}, {{
'7',
'2'}}, {{
'7',
'3'}}, {{
'7',
'4'}}, {{
'7',
'5'}}, {{
'7',
'6'}}, {{
'7',
'7'}}, {{
'7',
'8'}}, {{
'7',
'9'}},
18758 {{
'8',
'0'}}, {{
'8',
'1'}}, {{
'8',
'2'}}, {{
'8',
'3'}}, {{
'8',
'4'}}, {{
'8',
'5'}}, {{
'8',
'6'}}, {{
'8',
'7'}}, {{
'8',
'8'}}, {{
'8',
'9'}},
18759 {{
'9',
'0'}}, {{
'9',
'1'}}, {{
'9',
'2'}}, {{
'9',
'3'}}, {{
'9',
'4'}}, {{
'9',
'5'}}, {{
'9',
'6'}}, {{
'9',
'7'}}, {{
'9',
'8'}}, {{
'9',
'9'}},
18766 o->write_character(
'0');
18771 auto buffer_ptr = number_buffer.begin();
18773 number_unsigned_t abs_value;
18775 unsigned int n_chars{};
18777 if (is_negative_number(x))
18780 abs_value = remove_sign(
static_cast<number_integer_t
>(x));
18783 n_chars = 1 + count_digits(abs_value);
18787 abs_value =
static_cast<number_unsigned_t
>(x);
18788 n_chars = count_digits(abs_value);
18792 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18796 buffer_ptr += n_chars;
18800 while (abs_value >= 100)
18802 const auto digits_index =
static_cast<unsigned>((abs_value % 100));
18804 *(--buffer_ptr) = digits_to_99[digits_index][1];
18805 *(--buffer_ptr) = digits_to_99[digits_index][0];
18808 if (abs_value >= 10)
18810 const auto digits_index =
static_cast<unsigned>(abs_value);
18811 *(--buffer_ptr) = digits_to_99[digits_index][1];
18812 *(--buffer_ptr) = digits_to_99[digits_index][0];
18816 *(--buffer_ptr) =
static_cast<char>(
'0' + abs_value);
18819 o->write_characters(number_buffer.data(), n_chars);
18830 void dump_float(number_float_t x)
18833 if (!std::isfinite(x))
18835 o->write_characters(
"null", 4);
18844 static constexpr bool is_ieee_single_or_double
18845 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
18846 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
18848 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18851 void dump_float(number_float_t x, std::true_type )
18853 auto* begin = number_buffer.data();
18854 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18856 o->write_characters(begin,
static_cast<size_t>(end - begin));
18859 void dump_float(number_float_t x, std::false_type )
18862 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18866 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(),
"%.*g", d, x);
18869 JSON_ASSERT(len > 0);
18871 JSON_ASSERT(
static_cast<std::size_t
>(len) < number_buffer.size());
18874 if (thousands_sep !=
'\0')
18877 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18878 std::fill(end, number_buffer.end(),
'\0');
18879 JSON_ASSERT((end - number_buffer.begin()) <= len);
18880 len = (end - number_buffer.begin());
18884 if (decimal_point !=
'\0' && decimal_point !=
'.')
18887 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18888 if (dec_pos != number_buffer.end())
18894 o->write_characters(number_buffer.data(),
static_cast<std::size_t
>(len));
18897 const bool value_is_int_like =
18898 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18901 return c ==
'.' || c ==
'e';
18904 if (value_is_int_like)
18906 o->write_characters(
".0", 2);
18931 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep,
const std::uint8_t
byte)
noexcept
18933 static const std::array<std::uint8_t, 400> utf8d =
18936 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18937 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18938 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18939 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18940 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
18941 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
18942 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
18943 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3,
18944 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
18945 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1,
18946 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1,
18947 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
18948 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1,
18949 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
18953 JSON_ASSERT(
byte < utf8d.size());
18954 const std::uint8_t type = utf8d[byte];
18956 codep = (state != UTF8_ACCEPT)
18957 ? (
byte & 0x3fu) | (codep << 6u)
18958 : (0xFFu >> type) & (byte);
18960 const std::size_t index = 256u +
static_cast<size_t>(state) * 16u +
static_cast<size_t>(type);
18961 JSON_ASSERT(index < utf8d.size());
18962 state = utf8d[index];
18971 number_unsigned_t remove_sign(number_unsigned_t x)
18973 JSON_ASSERT(
false);
18986 inline number_unsigned_t remove_sign(number_integer_t x)
noexcept
18988 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)());
18989 return static_cast<number_unsigned_t
>(-(x + 1)) + 1;
18994 output_adapter_t<char> o =
nullptr;
18997 std::array<char, 64> number_buffer{{}};
19000 const std::lconv* loc =
nullptr;
19002 const char thousands_sep =
'\0';
19004 const char decimal_point =
'\0';
19007 std::array<char, 512> string_buffer{{}};
19019NLOHMANN_JSON_NAMESPACE_END
19036#include <functional>
19037#include <initializer_list>
19040#include <stdexcept>
19041#include <type_traits>
19050NLOHMANN_JSON_NAMESPACE_BEGIN
19054template <
class Key,
class T,
class IgnoredLess = std::less<Key>,
19055 class Allocator = std::allocator<std::pair<const Key, T>>>
19058 using key_type = Key;
19059 using mapped_type = T;
19060 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19061 using iterator =
typename Container::iterator;
19062 using const_iterator =
typename Container::const_iterator;
19063 using size_type =
typename Container::size_type;
19064 using value_type =
typename Container::value_type;
19065#ifdef JSON_HAS_CPP_14
19066 using key_compare = std::equal_to<>;
19068 using key_compare = std::equal_to<Key>;
19073 ordered_map()
noexcept(
noexcept(Container())) : Container{} {}
19074 explicit ordered_map(
const Allocator& alloc)
noexcept(
noexcept(Container(alloc))) : Container{alloc} {}
19075 template <
class It>
19076 ordered_map(It first, It last,
const Allocator& alloc = Allocator())
19077 : Container{first, last, alloc} {}
19078 ordered_map(std::initializer_list<value_type> init,
const Allocator& alloc = Allocator() )
19079 : Container{init, alloc} {}
19081 std::pair<iterator, bool> emplace(
const key_type& key, T&& t)
19083 for (
auto it = this->begin(); it != this->end(); ++it)
19085 if (m_compare(it->first, key))
19087 return {it,
false};
19090 Container::emplace_back(key, std::forward<T>(t));
19091 return {std::prev(this->end()),
true};
19094 template<
class KeyType, detail::enable_if_t<
19095 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19096 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19098 for (
auto it = this->begin(); it != this->end(); ++it)
19100 if (m_compare(it->first, key))
19102 return {it,
false};
19105 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19106 return {std::prev(this->end()),
true};
19109 T& operator[](
const key_type& key)
19111 return emplace(key, T{}).first->second;
19114 template<
class KeyType, detail::enable_if_t<
19115 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19116 T & operator[](KeyType && key)
19118 return emplace(std::forward<KeyType>(key), T{}).first->second;
19121 const T& operator[](
const key_type& key)
const
19126 template<
class KeyType, detail::enable_if_t<
19127 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19128 const T & operator[](KeyType && key)
const
19130 return at(std::forward<KeyType>(key));
19133 T& at(
const key_type& key)
19135 for (
auto it = this->begin(); it != this->end(); ++it)
19137 if (m_compare(it->first, key))
19143 JSON_THROW(std::out_of_range(
"key not found"));
19146 template<
class KeyType, detail::enable_if_t<
19147 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19148 T & at(KeyType && key)
19150 for (
auto it = this->begin(); it != this->end(); ++it)
19152 if (m_compare(it->first, key))
19158 JSON_THROW(std::out_of_range(
"key not found"));
19161 const T& at(
const key_type& key)
const
19163 for (
auto it = this->begin(); it != this->end(); ++it)
19165 if (m_compare(it->first, key))
19171 JSON_THROW(std::out_of_range(
"key not found"));
19174 template<
class KeyType, detail::enable_if_t<
19175 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19176 const T & at(KeyType && key)
const
19178 for (
auto it = this->begin(); it != this->end(); ++it)
19180 if (m_compare(it->first, key))
19186 JSON_THROW(std::out_of_range(
"key not found"));
19189 size_type erase(
const key_type& key)
19191 for (
auto it = this->begin(); it != this->end(); ++it)
19193 if (m_compare(it->first, key))
19196 for (
auto next = it; ++next != this->end(); ++it)
19199 new (&*it) value_type{std::move(*next)};
19201 Container::pop_back();
19208 template<
class KeyType, detail::enable_if_t<
19209 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19210 size_type erase(KeyType && key)
19212 for (
auto it = this->begin(); it != this->end(); ++it)
19214 if (m_compare(it->first, key))
19217 for (
auto next = it; ++next != this->end(); ++it)
19220 new (&*it) value_type{std::move(*next)};
19222 Container::pop_back();
19229 iterator erase(iterator pos)
19231 return erase(pos, std::next(pos));
19234 iterator erase(iterator first, iterator last)
19241 const auto elements_affected = std::distance(first, last);
19242 const auto offset = std::distance(Container::begin(), first);
19264 for (
auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19267 new (&*it) value_type{std::move(*std::next(it, elements_affected))};
19275 Container::resize(this->size() -
static_cast<size_type
>(elements_affected));
19284 return Container::begin() + offset;
19287 size_type count(
const key_type& key)
const
19289 for (
auto it = this->begin(); it != this->end(); ++it)
19291 if (m_compare(it->first, key))
19299 template<
class KeyType, detail::enable_if_t<
19300 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19301 size_type count(KeyType && key)
const
19303 for (
auto it = this->begin(); it != this->end(); ++it)
19305 if (m_compare(it->first, key))
19313 iterator find(
const key_type& key)
19315 for (
auto it = this->begin(); it != this->end(); ++it)
19317 if (m_compare(it->first, key))
19322 return Container::end();
19325 template<
class KeyType, detail::enable_if_t<
19326 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value,
int> = 0>
19327 iterator find(KeyType && key)
19329 for (
auto it = this->begin(); it != this->end(); ++it)
19331 if (m_compare(it->first, key))
19336 return Container::end();
19339 const_iterator find(
const key_type& key)
const
19341 for (
auto it = this->begin(); it != this->end(); ++it)
19343 if (m_compare(it->first, key))
19348 return Container::end();
19351 std::pair<iterator, bool> insert( value_type&& value )
19353 return emplace(value.first, std::move(value.second));
19356 std::pair<iterator, bool> insert(
const value_type& value )
19358 for (
auto it = this->begin(); it != this->end(); ++it)
19360 if (m_compare(it->first, value.first))
19362 return {it,
false};
19365 Container::push_back(value);
19366 return {--this->end(),
true};
19369 template<
typename InputIt>
19370 using require_input_iter =
typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19371 std::input_iterator_tag>::value>::type;
19373 template<
typename InputIt,
typename = require_input_iter<InputIt>>
19374 void insert(InputIt first, InputIt last)
19376 for (
auto it = first; it != last; ++it)
19383 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19386NLOHMANN_JSON_NAMESPACE_END
19389#if defined(JSON_HAS_CPP_17)
19390 #if JSON_HAS_STATIC_RTTI
19393 #include <string_view>
19401NLOHMANN_JSON_NAMESPACE_BEGIN
19421NLOHMANN_BASIC_JSON_TPL_DECLARATION
19423 :
public ::nlohmann::detail::json_base_class<CustomBaseClass>
19429 friend class ::nlohmann::json_pointer;
19433 template<
typename BasicJsonType,
typename InputType>
19434 friend class ::nlohmann::detail::parser;
19435 friend ::nlohmann::detail::serializer<basic_json>;
19436 template<
typename BasicJsonType>
19437 friend class ::nlohmann::detail::iter_impl;
19438 template<
typename BasicJsonType,
typename CharType>
19439 friend class ::nlohmann::detail::binary_writer;
19440 template<
typename BasicJsonType,
typename InputType,
typename SAX>
19441 friend class ::nlohmann::detail::binary_reader;
19442 template<
typename BasicJsonType>
19443 friend class ::nlohmann::detail::json_sax_dom_parser;
19444 template<
typename BasicJsonType>
19445 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19446 friend class ::nlohmann::detail::exception;
19450 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19452 JSON_PRIVATE_UNLESS_TESTED:
19454 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19456 template<
typename InputAdapterType>
19457 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19458 InputAdapterType adapter,
19459 detail::parser_callback_t<basic_json>cb =
nullptr,
19460 const bool allow_exceptions =
true,
19461 const bool ignore_comments =
false
19464 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19465 std::move(cb), allow_exceptions, ignore_comments);
19469 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19470 template<
typename BasicJsonType>
19471 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19472 template<
typename BasicJsonType>
19473 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19474 template<
typename Iterator>
19475 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19476 template<
typename Base>
using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19478 template<
typename CharType>
19479 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19481 template<
typename InputType>
19482 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19483 template<
typename CharType>
using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19485 JSON_PRIVATE_UNLESS_TESTED:
19486 using serializer = ::nlohmann::detail::serializer<basic_json>;
19492 template<
typename T,
typename SFINAE>
19493 using json_serializer = JSONSerializer<T, SFINAE>;
19548 using pointer =
typename std::allocator_traits<allocator_type>::pointer;
19550 using const_pointer =
typename std::allocator_traits<allocator_type>::const_pointer;
19572 JSON_HEDLEY_WARN_UNUSED_RESULT
19577 result[
"copyright"] =
"(C) 2013-2023 Niels Lohmann";
19578 result[
"name"] =
"JSON for Modern C++";
19579 result[
"url"] =
"https://github.com/nlohmann/json";
19580 result[
"version"][
"string"] =
19581 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR),
'.',
19582 std::to_string(NLOHMANN_JSON_VERSION_MINOR),
'.',
19583 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19584 result[
"version"][
"major"] = NLOHMANN_JSON_VERSION_MAJOR;
19585 result[
"version"][
"minor"] = NLOHMANN_JSON_VERSION_MINOR;
19586 result[
"version"][
"patch"] = NLOHMANN_JSON_VERSION_PATCH;
19589 result[
"platform"] =
"win32";
19590#elif defined __linux__
19591 result[
"platform"] =
"linux";
19592#elif defined __APPLE__
19593 result[
"platform"] =
"apple";
19594#elif defined __unix__
19595 result[
"platform"] =
"unix";
19597 result[
"platform"] =
"unknown";
19600#if defined(__ICC) || defined(__INTEL_COMPILER)
19601 result[
"compiler"] = {{
"family",
"icc"}, {
"version", __INTEL_COMPILER}};
19602#elif defined(__clang__)
19603 result[
"compiler"] = {{
"family",
"clang"}, {
"version", __clang_version__}};
19604#elif defined(__GNUC__) || defined(__GNUG__)
19605 result[
"compiler"] = {{
"family",
"gcc"}, {
"version", detail::concat(
19606 std::to_string(__GNUC__),
'.',
19607 std::to_string(__GNUC_MINOR__),
'.',
19608 std::to_string(__GNUC_PATCHLEVEL__))
19611#elif defined(__HP_cc) || defined(__HP_aCC)
19612 result[
"compiler"] =
"hp"
19613#elif defined(__IBMCPP__)
19614 result[
"compiler"] = {{
"family",
"ilecpp"}, {
"version", __IBMCPP__}};
19615#elif defined(_MSC_VER)
19616 result[
"compiler"] = {{
"family",
"msvc"}, {
"version", _MSC_VER}};
19617#elif defined(__PGI)
19618 result[
"compiler"] = {{
"family",
"pgcpp"}, {
"version", __PGI}};
19619#elif defined(__SUNPRO_CC)
19620 result[
"compiler"] = {{
"family",
"sunpro"}, {
"version", __SUNPRO_CC}};
19622 result[
"compiler"] = {{
"family",
"unknown"}, {
"version",
"unknown"}};
19625#if defined(_MSVC_LANG)
19626 result[
"compiler"][
"c++"] = std::to_string(_MSVC_LANG);
19627#elif defined(__cplusplus)
19628 result[
"compiler"][
"c++"] = std::to_string(__cplusplus);
19630 result[
"compiler"][
"c++"] =
"unknown";
19648#if defined(JSON_HAS_CPP_14)
19651 using default_object_comparator_t = std::less<>;
19661 AllocatorType<std::pair<
const StringType,
19666 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19690 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19701 template<
typename T,
typename... Args>
19702 JSON_HEDLEY_RETURNS_NON_NULL
19705 AllocatorType<T> alloc;
19706 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19708 auto deleter = [&](T * obj)
19710 AllocatorTraits::deallocate(alloc, obj, 1);
19712 std::unique_ptr<T,
decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19713 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19714 JSON_ASSERT(obj !=
nullptr);
19715 return obj.release();
19722 JSON_PRIVATE_UNLESS_TESTED:
19782 case value_t::object:
19784 object = create<object_t>();
19788 case value_t::array:
19790 array = create<array_t>();
19794 case value_t::string:
19796 string = create<string_t>(
"");
19800 case value_t::binary:
19802 binary = create<binary_t>();
19806 case value_t::boolean:
19808 boolean =
static_cast<boolean_t>(
false);
19812 case value_t::number_integer:
19818 case value_t::number_unsigned:
19824 case value_t::number_float:
19830 case value_t::null:
19836 case value_t::discarded:
19840 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19842 JSON_THROW(other_error::create(500,
"961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3",
nullptr));
19879 void destroy(value_t t)
19882 (t == value_t::object &&
object ==
nullptr) ||
19883 (t == value_t::array && array ==
nullptr) ||
19884 (t == value_t::string &&
string ==
nullptr) ||
19885 (t == value_t::binary && binary ==
nullptr)
19891 if (t == value_t::array || t == value_t::object)
19894 std::vector<basic_json> stack;
19897 if (t == value_t::array)
19899 stack.reserve(
array->size());
19900 std::move(
array->begin(),
array->end(), std::back_inserter(stack));
19904 stack.reserve(
object->size());
19905 for (
auto&& it : *
object)
19907 stack.push_back(std::move(it.second));
19911 while (!stack.empty())
19914 basic_json current_item(std::move(stack.back()));
19919 if (current_item.is_array())
19921 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19923 current_item.m_data.m_value.array->clear();
19925 else if (current_item.is_object())
19927 for (
auto&& it : *current_item.m_data.m_value.
object)
19929 stack.push_back(std::move(it.second));
19932 current_item.m_data.m_value.object->clear();
19942 case value_t::object:
19944 AllocatorType<object_t> alloc;
19945 std::allocator_traits<
decltype(alloc)>::destroy(alloc,
object);
19946 std::allocator_traits<
decltype(alloc)>::deallocate(alloc,
object, 1);
19950 case value_t::array:
19952 AllocatorType<array_t> alloc;
19953 std::allocator_traits<
decltype(alloc)>::destroy(alloc, array);
19954 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, array, 1);
19958 case value_t::string:
19960 AllocatorType<string_t> alloc;
19961 std::allocator_traits<
decltype(alloc)>::destroy(alloc,
string);
19962 std::allocator_traits<
decltype(alloc)>::deallocate(alloc,
string, 1);
19966 case value_t::binary:
19968 AllocatorType<binary_t> alloc;
19969 std::allocator_traits<
decltype(alloc)>::destroy(alloc, binary);
19970 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, binary, 1);
19974 case value_t::null:
19975 case value_t::boolean:
19976 case value_t::number_integer:
19977 case value_t::number_unsigned:
19978 case value_t::number_float:
19979 case value_t::discarded:
20009 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object !=
nullptr);
20010 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array !=
nullptr);
20011 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string !=
nullptr);
20012 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary !=
nullptr);
20014#if JSON_DIAGNOSTICS
20018 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [
this](
const basic_json & j)
20020 return j.m_parent ==
this;
20025 static_cast<void>(check_parents);
20030#if JSON_DIAGNOSTICS
20031 switch (m_data.m_type)
20033 case value_t::array:
20035 for (
auto& element : *m_data.m_value.array)
20037 element.m_parent =
this;
20042 case value_t::object:
20044 for (
auto& element : *m_data.m_value.
object)
20046 element.second.m_parent =
this;
20051 case value_t::null:
20052 case value_t::string:
20053 case value_t::boolean:
20054 case value_t::number_integer:
20055 case value_t::number_unsigned:
20056 case value_t::number_float:
20057 case value_t::binary:
20058 case value_t::discarded:
20065 iterator set_parents(iterator it,
typename iterator::difference_type count_set_parents)
20067#if JSON_DIAGNOSTICS
20068 for (
typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20070 (it + i)->m_parent =
this;
20073 static_cast<void>(count_set_parents);
20078 reference set_parent(reference j, std::size_t old_capacity =
static_cast<std::size_t
>(-1))
20080#if JSON_DIAGNOSTICS
20081 if (old_capacity !=
static_cast<std::size_t
>(-1))
20084 JSON_ASSERT(type() == value_t::array);
20085 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20095#ifdef JSON_HEDLEY_MSVC_VERSION
20096#pragma warning(push )
20097#pragma warning(disable : 4127)
20104#ifdef JSON_HEDLEY_MSVC_VERSION
20105#pragma warning( pop )
20110 static_cast<void>(j);
20111 static_cast<void>(old_capacity);
20143 assert_invariant();
20151 assert_invariant();
20156 template <
typename CompatibleType,
20157 typename U = detail::uncvref_t<CompatibleType>,
20158 detail::enable_if_t <
20161 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20162 std::forward<CompatibleType>(val))))
20164 JSONSerializer<U>::to_json(*
this, std::forward<CompatibleType>(val));
20166 assert_invariant();
20171 template <
typename BasicJsonType,
20172 detail::enable_if_t <
20176 using other_boolean_t =
typename BasicJsonType::boolean_t;
20177 using other_number_float_t =
typename BasicJsonType::number_float_t;
20178 using other_number_integer_t =
typename BasicJsonType::number_integer_t;
20179 using other_number_unsigned_t =
typename BasicJsonType::number_unsigned_t;
20180 using other_string_t =
typename BasicJsonType::string_t;
20181 using other_object_t =
typename BasicJsonType::object_t;
20182 using other_array_t =
typename BasicJsonType::array_t;
20183 using other_binary_t =
typename BasicJsonType::binary_t;
20185 switch (val.type())
20187 case value_t::boolean:
20188 JSONSerializer<other_boolean_t>::to_json(*
this, val.template get<other_boolean_t>());
20190 case value_t::number_float:
20191 JSONSerializer<other_number_float_t>::to_json(*
this, val.template get<other_number_float_t>());
20193 case value_t::number_integer:
20194 JSONSerializer<other_number_integer_t>::to_json(*
this, val.template get<other_number_integer_t>());
20196 case value_t::number_unsigned:
20197 JSONSerializer<other_number_unsigned_t>::to_json(*
this, val.template get<other_number_unsigned_t>());
20199 case value_t::string:
20200 JSONSerializer<other_string_t>::to_json(*
this, val.template get_ref<const other_string_t&>());
20202 case value_t::object:
20203 JSONSerializer<other_object_t>::to_json(*
this, val.template get_ref<const other_object_t&>());
20205 case value_t::array:
20206 JSONSerializer<other_array_t>::to_json(*
this, val.template get_ref<const other_array_t&>());
20208 case value_t::binary:
20209 JSONSerializer<other_binary_t>::to_json(*
this, val.template get_ref<const other_binary_t&>());
20211 case value_t::null:
20214 case value_t::discarded:
20215 m_data.m_type = value_t::discarded;
20218 JSON_ASSERT(
false);
20220 JSON_ASSERT(m_data.m_type == val.type());
20222 assert_invariant();
20228 bool type_deduction =
true,
20229 value_t manual_type = value_t::array)
20233 bool is_an_object = std::all_of(init.begin(), init.end(),
20239 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20243 if (!type_deduction)
20246 if (manual_type == value_t::array)
20248 is_an_object =
false;
20252 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20254 JSON_THROW(type_error::create(301,
"cannot create object from initializer list",
nullptr));
20261 m_data.m_type = value_t::object;
20262 m_data.m_value = value_t::object;
20264 for (
auto& element_ref : init)
20266 auto element = element_ref.moved_or_copied();
20267 m_data.m_value.object->emplace(
20268 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20269 std::move((*element.m_data.m_value.array)[1]));
20275 m_data.m_type = value_t::array;
20276 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20280 assert_invariant();
20285 JSON_HEDLEY_WARN_UNUSED_RESULT
20289 res.m_data.m_type = value_t::binary;
20290 res.m_data.m_value = init;
20296 JSON_HEDLEY_WARN_UNUSED_RESULT
20297 static basic_json binary(
const typename binary_t::container_type& init,
typename binary_t::subtype_type subtype)
20300 res.m_data.m_type = value_t::binary;
20301 res.m_data.m_value =
binary_t(init, subtype);
20307 JSON_HEDLEY_WARN_UNUSED_RESULT
20311 res.m_data.m_type = value_t::binary;
20312 res.m_data.m_value = std::move(init);
20318 JSON_HEDLEY_WARN_UNUSED_RESULT
20319 static basic_json binary(
typename binary_t::container_type&& init,
typename binary_t::subtype_type subtype)
20322 res.m_data.m_type = value_t::binary;
20323 res.m_data.m_value =
binary_t(std::move(init), subtype);
20329 JSON_HEDLEY_WARN_UNUSED_RESULT
20332 return basic_json(init,
false, value_t::array);
20337 JSON_HEDLEY_WARN_UNUSED_RESULT
20340 return basic_json(init,
false, value_t::object);
20349 assert_invariant();
20354 template <
class InputIT,
typename std::enable_if <
20355 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20356 std::is_same<InputIT, typename basic_json_t::const_iterator>::value,
int >::type = 0 >
20359 JSON_ASSERT(first.m_object !=
nullptr);
20360 JSON_ASSERT(last.m_object !=
nullptr);
20363 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20365 JSON_THROW(invalid_iterator::create(201,
"iterators are not compatible",
nullptr));
20369 m_data.m_type = first.m_object->m_data.m_type;
20372 switch (m_data.m_type)
20374 case value_t::boolean:
20375 case value_t::number_float:
20376 case value_t::number_integer:
20377 case value_t::number_unsigned:
20378 case value_t::string:
20380 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20381 || !last.m_it.primitive_iterator.is_end()))
20383 JSON_THROW(invalid_iterator::create(204,
"iterators out of range", first.m_object));
20388 case value_t::null:
20389 case value_t::object:
20390 case value_t::array:
20391 case value_t::binary:
20392 case value_t::discarded:
20397 switch (m_data.m_type)
20399 case value_t::number_integer:
20401 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20405 case value_t::number_unsigned:
20407 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20411 case value_t::number_float:
20413 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20417 case value_t::boolean:
20419 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20423 case value_t::string:
20425 m_data.m_value = *first.m_object->m_data.m_value.string;
20429 case value_t::object:
20431 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20432 last.m_it.object_iterator);
20436 case value_t::array:
20438 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20439 last.m_it.array_iterator);
20443 case value_t::binary:
20445 m_data.m_value = *first.m_object->m_data.m_value.binary;
20449 case value_t::null:
20450 case value_t::discarded:
20452 JSON_THROW(invalid_iterator::create(206, detail::concat(
"cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20456 assert_invariant();
20463 template<
typename JsonRef,
20464 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20465 std::is_same<typename JsonRef::value_type, basic_json>>::value,
int> = 0 >
20471 : json_base_class_t(other)
20473 m_data.m_type = other.m_data.m_type;
20477 switch (m_data.m_type)
20479 case value_t::object:
20481 m_data.m_value = *other.m_data.m_value.object;
20485 case value_t::array:
20487 m_data.m_value = *other.m_data.m_value.array;
20491 case value_t::string:
20493 m_data.m_value = *other.m_data.m_value.string;
20497 case value_t::boolean:
20499 m_data.m_value = other.m_data.m_value.boolean;
20503 case value_t::number_integer:
20505 m_data.m_value = other.m_data.m_value.number_integer;
20509 case value_t::number_unsigned:
20511 m_data.m_value = other.m_data.m_value.number_unsigned;
20515 case value_t::number_float:
20517 m_data.m_value = other.m_data.m_value.number_float;
20521 case value_t::binary:
20523 m_data.m_value = *other.m_data.m_value.binary;
20527 case value_t::null:
20528 case value_t::discarded:
20534 assert_invariant();
20540 : json_base_class_t(std::forward<json_base_class_t>(other)),
20541 m_data(std::move(other.m_data))
20544 other.assert_invariant(
false);
20547 other.m_data.m_type = value_t::null;
20548 other.m_data.m_value = {};
20551 assert_invariant();
20557 std::is_nothrow_move_constructible<value_t>::value&&
20558 std::is_nothrow_move_assignable<value_t>::value&&
20559 std::is_nothrow_move_constructible<json_value>::value&&
20560 std::is_nothrow_move_assignable<json_value>::value&&
20561 std::is_nothrow_move_assignable<json_base_class_t>::value
20568 swap(m_data.m_type, other.m_data.m_type);
20569 swap(m_data.m_value, other.m_data.m_value);
20570 json_base_class_t::operator=(std::move(other));
20573 assert_invariant();
20581 assert_invariant(
false);
20598 const char indent_char =
' ',
20599 const bool ensure_ascii =
false,
20607 s.dump(*
this,
true, ensure_ascii,
static_cast<unsigned int>(indent));
20611 s.dump(*
this,
false, ensure_ascii, 0);
20621 return m_data.m_type;
20628 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20635 return is_array() || is_object();
20642 return m_data.m_type == value_t::null;
20649 return m_data.m_type == value_t::boolean;
20656 return is_number_integer() || is_number_float();
20663 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20670 return m_data.m_type == value_t::number_unsigned;
20677 return m_data.m_type == value_t::number_float;
20684 return m_data.m_type == value_t::object;
20691 return m_data.m_type == value_t::array;
20698 return m_data.m_type == value_t::string;
20705 return m_data.m_type == value_t::binary;
20712 return m_data.m_type == value_t::discarded;
20719 return m_data.m_type;
20732 if (JSON_HEDLEY_LIKELY(is_boolean()))
20734 return m_data.m_value.boolean;
20737 JSON_THROW(type_error::create(302, detail::concat(
"type must be boolean, but is ", type_name()),
this));
20743 return is_object() ? m_data.m_value.object :
nullptr;
20749 return is_object() ? m_data.m_value.object :
nullptr;
20755 return is_array() ? m_data.m_value.array :
nullptr;
20761 return is_array() ? m_data.m_value.array :
nullptr;
20767 return is_string() ? m_data.m_value.string :
nullptr;
20773 return is_string() ? m_data.m_value.string :
nullptr;
20779 return is_boolean() ? &m_data.m_value.boolean :
nullptr;
20785 return is_boolean() ? &m_data.m_value.boolean :
nullptr;
20791 return is_number_integer() ? &m_data.m_value.number_integer :
nullptr;
20797 return is_number_integer() ? &m_data.m_value.number_integer :
nullptr;
20803 return is_number_unsigned() ? &m_data.m_value.number_unsigned :
nullptr;
20809 return is_number_unsigned() ? &m_data.m_value.number_unsigned :
nullptr;
20815 return is_number_float() ? &m_data.m_value.number_float :
nullptr;
20821 return is_number_float() ? &m_data.m_value.number_float :
nullptr;
20827 return is_binary() ? m_data.m_value.binary :
nullptr;
20833 return is_binary() ? m_data.m_value.binary :
nullptr;
20847 template<
typename ReferenceType,
typename ThisType>
20851 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20853 if (JSON_HEDLEY_LIKELY(ptr !=
nullptr))
20858 JSON_THROW(type_error::create(303, detail::concat(
"incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20868 template<
typename PointerType,
typename std::enable_if<
20869 std::is_pointer<PointerType>::value,
int>::type = 0>
20873 return get_impl_ptr(
static_cast<PointerType
>(
nullptr));
20878 template <
typename PointerType,
typename std::enable_if <
20879 std::is_pointer<PointerType>::value&&
20880 std::is_const<typename std::remove_pointer<PointerType>::type>::value,
int >::type = 0 >
20881 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const
basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20884 return get_impl_ptr(
static_cast<PointerType
>(
nullptr));
20926 template <
typename ValueType,
20927 detail::enable_if_t <
20932 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20934 auto ret = ValueType();
20935 JSONSerializer<ValueType>::from_json(*
this, ret);
20969 template <
typename ValueType,
20970 detail::enable_if_t <
20974 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20976 return JSONSerializer<ValueType>::from_json(*
this);
20994 template <
typename BasicJsonType,
20995 detail::enable_if_t <
21017 template<
typename BasicJsonType,
21018 detail::enable_if_t<
21019 std::is_same<BasicJsonType, basic_json_t>::value,
21030 template<
typename PointerType,
21031 detail::enable_if_t<
21032 std::is_pointer<PointerType>::value,
21035 ->
decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21038 return get_ptr<PointerType>();
21065 template <
typename ValueTypeCV,
typename ValueType = detail::uncvref_t<ValueTypeCV>>
21066#if defined(JSON_HAS_CPP_14)
21070 noexcept(std::declval<const
basic_json_t&>().template get_impl<ValueType>(
detail::priority_tag<4> {})))
21076 static_assert(!std::is_reference<ValueTypeCV>::value,
21077 "get() cannot be used with reference types, you might want to use get_ref()");
21108 template<
typename PointerType,
typename std::enable_if<
21109 std::is_pointer<PointerType>::value,
int>::type = 0>
21110 auto get() noexcept -> decltype(std::declval<
basic_json_t&>().template get_ptr<PointerType>())
21113 return get_ptr<PointerType>();
21118 template <
typename ValueType,
21119 detail::enable_if_t <
21123 ValueType &
get_to(ValueType& v)
const noexcept(
noexcept(
21124 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21126 JSONSerializer<ValueType>::from_json(*
this, v);
21132 template<
typename ValueType,
21133 detail::enable_if_t <
21136 ValueType & get_to(ValueType& v)
const
21143 typename T, std::size_t N,
21144 typename Array = T (&)[N],
21145 detail::enable_if_t <
21147 Array get_to(T (&v)[N])
const
21148 noexcept(
noexcept(JSONSerializer<Array>::from_json(
21149 std::declval<const basic_json_t&>(), v)))
21151 JSONSerializer<Array>::from_json(*
this, v);
21157 template<
typename ReferenceType,
typename std::enable_if<
21158 std::is_reference<ReferenceType>::value,
int>::type = 0>
21162 return get_ref_impl<ReferenceType>(*
this);
21167 template <
typename ReferenceType,
typename std::enable_if <
21168 std::is_reference<ReferenceType>::value&&
21169 std::is_const<typename std::remove_reference<ReferenceType>::type>::value,
int >::type = 0 >
21173 return get_ref_impl<ReferenceType>(*
this);
21205 template <
typename ValueType,
typename std::enable_if <
21213#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21216#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21220 >::value,
int >::type = 0 >
21221 JSON_EXPLICIT
operator ValueType()
const
21224 return get<ValueType>();
21233 JSON_THROW(type_error::create(302, detail::concat(
"type must be binary, but is ", type_name()),
this));
21236 return *get_ptr<binary_t*>();
21245 JSON_THROW(type_error::create(302, detail::concat(
"type must be binary, but is ", type_name()),
this));
21248 return *get_ptr<const binary_t*>();
21266 if (JSON_HEDLEY_LIKELY(is_array()))
21270 return set_parent(m_data.m_value.array->at(idx));
21272 JSON_CATCH (std::out_of_range&)
21275 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"),
this));
21280 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
21289 if (JSON_HEDLEY_LIKELY(is_array()))
21293 return m_data.m_value.array->at(idx);
21295 JSON_CATCH (std::out_of_range&)
21298 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"),
this));
21303 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
21312 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21314 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
21317 auto it = m_data.m_value.object->find(key);
21318 if (it == m_data.m_value.object->end())
21320 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", key,
"' not found"),
this));
21322 return set_parent(it->second);
21327 template<
class KeyType, detail::enable_if_t<
21328 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21332 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21334 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
21337 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21338 if (it == m_data.m_value.object->end())
21340 JSON_THROW(out_of_range::create(403, detail::concat(
"key '",
string_t(std::forward<KeyType>(key)),
"' not found"),
this));
21342 return set_parent(it->second);
21350 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21352 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
21355 auto it = m_data.m_value.object->find(key);
21356 if (it == m_data.m_value.object->end())
21358 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", key,
"' not found"),
this));
21365 template<
class KeyType, detail::enable_if_t<
21366 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21370 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21372 JSON_THROW(type_error::create(304, detail::concat(
"cannot use at() with ", type_name()),
this));
21375 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21376 if (it == m_data.m_value.object->end())
21378 JSON_THROW(out_of_range::create(403, detail::concat(
"key '",
string_t(std::forward<KeyType>(key)),
"' not found"),
this));
21390 m_data.m_type = value_t::array;
21391 m_data.
m_value.array = create<array_t>();
21392 assert_invariant();
21396 if (JSON_HEDLEY_LIKELY(is_array()))
21399 if (idx >= m_data.m_value.array->size())
21401#if JSON_DIAGNOSTICS
21403 const auto old_size = m_data.m_value.array->size();
21404 const auto old_capacity = m_data.m_value.array->capacity();
21406 m_data.m_value.array->resize(idx + 1);
21408#if JSON_DIAGNOSTICS
21409 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21417 set_parents(begin() +
static_cast<typename iterator::difference_type
>(old_size),
static_cast<typename iterator::difference_type
>(idx + 1 - old_size));
21420 assert_invariant();
21423 return m_data.m_value.array->operator[](idx);
21426 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a numeric argument with ", type_name()),
this));
21434 if (JSON_HEDLEY_LIKELY(is_array()))
21436 return m_data.
m_value.array->operator[](idx);
21439 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a numeric argument with ", type_name()),
this));
21449 m_data.m_type = value_t::object;
21450 m_data.
m_value.object = create<object_t>();
21451 assert_invariant();
21455 if (JSON_HEDLEY_LIKELY(is_object()))
21457 auto result = m_data.m_value.object->emplace(std::move(key),
nullptr);
21458 return set_parent(result.first->second);
21461 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
21469 if (JSON_HEDLEY_LIKELY(is_object()))
21471 auto it = m_data.
m_value.object->find(key);
21472 JSON_ASSERT(it != m_data.m_value.object->end());
21476 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
21481 template<
typename T>
21482 reference operator[](T* key)
21484 return operator[](
typename object_t::key_type(key));
21487 template<
typename T>
21488 const_reference operator[](T* key)
const
21490 return operator[](
typename object_t::key_type(key));
21495 template<
class KeyType, detail::enable_if_t<
21496 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int > = 0 >
21502 m_data.m_type = value_t::object;
21503 m_data.
m_value.object = create<object_t>();
21504 assert_invariant();
21508 if (JSON_HEDLEY_LIKELY(is_object()))
21510 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key),
nullptr);
21511 return set_parent(result.first->second);
21514 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
21519 template<
class KeyType, detail::enable_if_t<
21520 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int > = 0 >
21524 if (JSON_HEDLEY_LIKELY(is_object()))
21526 auto it = m_data.
m_value.object->find(std::forward<KeyType>(key));
21527 JSON_ASSERT(it != m_data.m_value.object->end());
21531 JSON_THROW(type_error::create(305, detail::concat(
"cannot use operator[] with a string argument with ", type_name()),
this));
21535 template<
typename KeyType>
21537 object_comparator_t,
const typename object_t::key_type&, KeyType >;
21539 template<
typename ValueType>
21540 using value_return_type = std::conditional <
21541 detail::is_c_string_uncvref<ValueType>::value,
21542 string_t,
typename std::decay<ValueType>::type >;
21547 template <
class ValueType, detail::enable_if_t <
21550 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21551 ValueType
value(
const typename object_t::key_type& key,
const ValueType& default_value)
const
21554 if (JSON_HEDLEY_LIKELY(is_object()))
21557 const auto it = find(key);
21560 return it->template get<ValueType>();
21563 return default_value;
21566 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
21571 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21572 detail::enable_if_t <
21575 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21576 ReturnType
value(
const typename object_t::key_type& key, ValueType && default_value)
const
21579 if (JSON_HEDLEY_LIKELY(is_object()))
21582 const auto it = find(key);
21585 return it->template get<ReturnType>();
21588 return std::forward<ValueType>(default_value);
21591 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
21596 template <
class ValueType,
class KeyType, detail::enable_if_t <
21598 && !detail::is_json_pointer<KeyType>::value
21599 && is_comparable_with_object_key<KeyType>::value
21601 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21602 ValueType
value(KeyType && key,
const ValueType& default_value)
const
21605 if (JSON_HEDLEY_LIKELY(is_object()))
21608 const auto it = find(std::forward<KeyType>(key));
21611 return it->template get<ValueType>();
21614 return default_value;
21617 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
21622 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21623 detail::enable_if_t <
21625 && !detail::is_json_pointer<KeyType>::value
21626 && is_comparable_with_object_key<KeyType>::value
21628 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21629 ReturnType
value(KeyType && key, ValueType && default_value)
const
21632 if (JSON_HEDLEY_LIKELY(is_object()))
21635 const auto it = find(std::forward<KeyType>(key));
21638 return it->template get<ReturnType>();
21641 return std::forward<ValueType>(default_value);
21644 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
21649 template <
class ValueType, detail::enable_if_t <
21651 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21655 if (JSON_HEDLEY_LIKELY(is_object()))
21660 return ptr.
get_checked(
this).template get<ValueType>();
21664 return default_value;
21668 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
21673 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21674 detail::enable_if_t <
21676 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21680 if (JSON_HEDLEY_LIKELY(is_object()))
21685 return ptr.
get_checked(
this).template get<ReturnType>();
21689 return std::forward<ValueType>(default_value);
21693 JSON_THROW(type_error::create(306, detail::concat(
"cannot use value() with ", type_name()),
this));
21696 template <
class ValueType,
class BasicJsonType, detail::enable_if_t <
21699 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21701 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr,
const ValueType& default_value)
const
21703 return value(ptr.convert(), default_value);
21706 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21707 detail::enable_if_t <
21710 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value,
int > = 0 >
21712 ReturnType
value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value)
const
21714 return value(ptr.convert(), std::forward<ValueType>(default_value));
21751 template <
class IteratorType, detail::enable_if_t <
21752 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21753 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int > = 0 >
21757 if (JSON_HEDLEY_UNLIKELY(
this != pos.m_object))
21759 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
21762 IteratorType result = end();
21764 switch (m_data.m_type)
21766 case value_t::boolean:
21767 case value_t::number_float:
21768 case value_t::number_integer:
21769 case value_t::number_unsigned:
21770 case value_t::string:
21771 case value_t::binary:
21773 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21775 JSON_THROW(invalid_iterator::create(205,
"iterator out of range",
this));
21780 AllocatorType<string_t> alloc;
21781 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21782 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21783 m_data.m_value.string =
nullptr;
21785 else if (is_binary())
21787 AllocatorType<binary_t> alloc;
21788 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21789 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21790 m_data.m_value.binary =
nullptr;
21793 m_data.m_type = value_t::null;
21794 assert_invariant();
21798 case value_t::object:
21800 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21804 case value_t::array:
21806 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21810 case value_t::null:
21811 case value_t::discarded:
21813 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21821 template <
class IteratorType, detail::enable_if_t <
21822 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21823 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value,
int > = 0 >
21824 IteratorType
erase(IteratorType first, IteratorType last)
21827 if (JSON_HEDLEY_UNLIKELY(
this != first.m_object ||
this != last.m_object))
21829 JSON_THROW(invalid_iterator::create(203,
"iterators do not fit current value",
this));
21832 IteratorType result = end();
21834 switch (m_data.m_type)
21836 case value_t::boolean:
21837 case value_t::number_float:
21838 case value_t::number_integer:
21839 case value_t::number_unsigned:
21840 case value_t::string:
21841 case value_t::binary:
21843 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21844 || !last.m_it.primitive_iterator.is_end()))
21846 JSON_THROW(invalid_iterator::create(204,
"iterators out of range",
this));
21851 AllocatorType<string_t> alloc;
21852 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21853 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21854 m_data.m_value.string =
nullptr;
21856 else if (is_binary())
21858 AllocatorType<binary_t> alloc;
21859 std::allocator_traits<
decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21860 std::allocator_traits<
decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21861 m_data.m_value.binary =
nullptr;
21864 m_data.m_type = value_t::null;
21865 assert_invariant();
21869 case value_t::object:
21871 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21872 last.m_it.object_iterator);
21876 case value_t::array:
21878 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21879 last.m_it.array_iterator);
21883 case value_t::null:
21884 case value_t::discarded:
21886 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21893 template <
typename KeyType, detail::enable_if_t <
21894 detail::has_erase_with_key_type<basic_json_t, KeyType>::value,
int > = 0 >
21895 size_type erase_internal(KeyType && key)
21898 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21900 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21903 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21906 template <
typename KeyType, detail::enable_if_t <
21907 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value,
int > = 0 >
21908 size_type erase_internal(KeyType && key)
21911 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21913 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21916 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21917 if (it != m_data.m_value.object->end())
21919 m_data.m_value.object->erase(it);
21933 return erase_internal(key);
21938 template<
class KeyType, detail::enable_if_t<
21939 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
21942 return erase_internal(std::forward<KeyType>(key));
21950 if (JSON_HEDLEY_LIKELY(is_array()))
21952 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21954 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"),
this));
21957 m_data.m_value.array->erase(m_data.m_value.array->begin() +
static_cast<difference_type>(idx));
21961 JSON_THROW(type_error::create(307, detail::concat(
"cannot use erase() with ", type_name()),
this));
21978 auto result = end();
21982 result.m_it.object_iterator = m_data.m_value.object->find(key);
21992 auto result = cend();
21996 result.m_it.object_iterator = m_data.m_value.object->find(key);
22004 template<
class KeyType, detail::enable_if_t<
22005 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
22008 auto result = end();
22012 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22020 template<
class KeyType, detail::enable_if_t<
22021 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
22024 auto result = cend();
22028 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22039 return is_object() ? m_data.m_value.object->count(key) : 0;
22044 template<
class KeyType, detail::enable_if_t<
22045 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
22049 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22054 bool contains(
const typename object_t::key_type& key)
const
22056 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22061 template<
class KeyType, detail::enable_if_t<
22062 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value,
int> = 0>
22065 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22075 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
22077 bool contains(
const typename ::nlohmann::json_pointer<BasicJsonType>& ptr)
const
22079 return ptr.contains(
this);
22096 result.set_begin();
22112 result.set_begin();
22189 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22192 return ref.items();
22200 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22203 return ref.items();
22210 return iteration_proxy<iterator>(*
this);
22215 iteration_proxy<const_iterator>
items() const noexcept
22217 return iteration_proxy<const_iterator>(*
this);
22233 switch (m_data.m_type)
22235 case value_t::null:
22241 case value_t::array:
22244 return m_data.m_value.array->empty();
22247 case value_t::object:
22250 return m_data.m_value.object->empty();
22253 case value_t::string:
22254 case value_t::boolean:
22255 case value_t::number_integer:
22256 case value_t::number_unsigned:
22257 case value_t::number_float:
22258 case value_t::binary:
22259 case value_t::discarded:
22272 switch (m_data.m_type)
22274 case value_t::null:
22280 case value_t::array:
22283 return m_data.m_value.array->size();
22286 case value_t::object:
22289 return m_data.m_value.object->size();
22292 case value_t::string:
22293 case value_t::boolean:
22294 case value_t::number_integer:
22295 case value_t::number_unsigned:
22296 case value_t::number_float:
22297 case value_t::binary:
22298 case value_t::discarded:
22311 switch (m_data.m_type)
22313 case value_t::array:
22316 return m_data.m_value.array->max_size();
22319 case value_t::object:
22322 return m_data.m_value.object->max_size();
22325 case value_t::null:
22326 case value_t::string:
22327 case value_t::boolean:
22328 case value_t::number_integer:
22329 case value_t::number_unsigned:
22330 case value_t::number_float:
22331 case value_t::binary:
22332 case value_t::discarded:
22354 switch (m_data.m_type)
22356 case value_t::number_integer:
22358 m_data.m_value.number_integer = 0;
22362 case value_t::number_unsigned:
22364 m_data.m_value.number_unsigned = 0;
22368 case value_t::number_float:
22370 m_data.m_value.number_float = 0.0;
22374 case value_t::boolean:
22376 m_data.m_value.boolean =
false;
22380 case value_t::string:
22382 m_data.m_value.string->clear();
22386 case value_t::binary:
22388 m_data.m_value.binary->clear();
22392 case value_t::array:
22394 m_data.m_value.array->clear();
22398 case value_t::object:
22400 m_data.m_value.object->clear();
22404 case value_t::null:
22405 case value_t::discarded:
22416 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22418 JSON_THROW(type_error::create(308, detail::concat(
"cannot use push_back() with ", type_name()),
this));
22424 m_data.m_type = value_t::array;
22425 m_data.m_value = value_t::array;
22426 assert_invariant();
22430 const auto old_capacity = m_data.m_value.array->capacity();
22431 m_data.m_value.array->push_back(std::move(val));
22432 set_parent(m_data.m_value.array->back(), old_capacity);
22440 push_back(std::move(val));
22449 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22451 JSON_THROW(type_error::create(308, detail::concat(
"cannot use push_back() with ", type_name()),
this));
22457 m_data.m_type = value_t::array;
22458 m_data.m_value = value_t::array;
22459 assert_invariant();
22463 const auto old_capacity = m_data.m_value.array->capacity();
22464 m_data.m_value.array->push_back(val);
22465 set_parent(m_data.m_value.array->back(), old_capacity);
22481 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22483 JSON_THROW(type_error::create(308, detail::concat(
"cannot use push_back() with ", type_name()),
this));
22489 m_data.m_type = value_t::object;
22490 m_data.m_value = value_t::object;
22491 assert_invariant();
22495 auto res = m_data.m_value.object->insert(val);
22496 set_parent(res.first->second);
22511 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22513 basic_json&& key = init.begin()->moved_or_copied();
22514 push_back(
typename object_t::value_type(
22515 std::move(key.get_ref<
string_t&>()), (init.begin() + 1)->moved_or_copied()));
22533 template<
class... Args>
22537 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22539 JSON_THROW(type_error::create(311, detail::concat(
"cannot use emplace_back() with ", type_name()),
this));
22545 m_data.m_type = value_t::array;
22546 m_data.m_value = value_t::array;
22547 assert_invariant();
22551 const auto old_capacity = m_data.m_value.array->capacity();
22552 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22553 return set_parent(m_data.m_value.array->back(), old_capacity);
22558 template<
class... Args>
22562 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22564 JSON_THROW(type_error::create(311, detail::concat(
"cannot use emplace() with ", type_name()),
this));
22570 m_data.m_type = value_t::object;
22571 m_data.m_value = value_t::object;
22572 assert_invariant();
22576 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22577 set_parent(res.first->second);
22581 it.m_it.object_iterator = res.first;
22584 return {it, res.second};
22590 template<
typename... Args>
22594 JSON_ASSERT(m_data.m_value.array !=
nullptr);
22596 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22597 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22598 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22613 if (JSON_HEDLEY_LIKELY(is_array()))
22616 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this))
22618 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
22622 return insert_iterator(pos, val);
22625 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
22632 return insert(pos, val);
22640 if (JSON_HEDLEY_LIKELY(is_array()))
22643 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this))
22645 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
22649 return insert_iterator(pos, cnt, val);
22652 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
22660 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22662 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
22666 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this))
22668 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
22672 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22674 JSON_THROW(invalid_iterator::create(210,
"iterators do not fit",
this));
22677 if (JSON_HEDLEY_UNLIKELY(first.m_object ==
this))
22679 JSON_THROW(invalid_iterator::create(211,
"passed iterators may not belong to container",
this));
22683 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22691 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22693 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
22697 if (JSON_HEDLEY_UNLIKELY(pos.m_object !=
this))
22699 JSON_THROW(invalid_iterator::create(202,
"iterator does not fit current value",
this));
22703 return insert_iterator(pos, ilist.begin(), ilist.end());
22711 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22713 JSON_THROW(type_error::create(309, detail::concat(
"cannot use insert() with ", type_name()),
this));
22717 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22719 JSON_THROW(invalid_iterator::create(210,
"iterators do not fit",
this));
22723 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22725 JSON_THROW(invalid_iterator::create(202,
"iterators first and last must point to objects",
this));
22728 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22735 update(j.
begin(), j.
end(), merge_objects);
22745 m_data.m_type = value_t::object;
22746 m_data.m_value.object = create<object_t>();
22747 assert_invariant();
22750 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22752 JSON_THROW(type_error::create(312, detail::concat(
"cannot use update() with ", type_name()),
this));
22756 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22758 JSON_THROW(invalid_iterator::create(210,
"iterators do not fit",
this));
22762 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22764 JSON_THROW(type_error::create(312, detail::concat(
"cannot use update() with ", first.m_object->type_name()), first.m_object));
22767 for (
auto it = first; it != last; ++it)
22769 if (merge_objects && it.value().is_object())
22771 auto it2 = m_data.m_value.object->find(it.key());
22772 if (it2 != m_data.m_value.object->end())
22774 it2->second.update(it.value(),
true);
22778 m_data.m_value.object->operator[](it.key()) = it.value();
22779#if JSON_DIAGNOSTICS
22780 m_data.m_value.object->operator[](it.key()).m_parent =
this;
22788 std::is_nothrow_move_constructible<value_t>::value&&
22789 std::is_nothrow_move_assignable<value_t>::value&&
22790 std::is_nothrow_move_constructible<json_value>::value&&
22791 std::is_nothrow_move_assignable<json_value>::value
22794 std::swap(m_data.m_type, other.m_data.m_type);
22795 std::swap(m_data.m_value, other.m_data.m_value);
22798 other.set_parents();
22799 assert_invariant();
22805 std::is_nothrow_move_constructible<value_t>::value&&
22806 std::is_nothrow_move_assignable<value_t>::value&&
22807 std::is_nothrow_move_constructible<json_value>::value&&
22808 std::is_nothrow_move_assignable<json_value>::value
22819 if (JSON_HEDLEY_LIKELY(is_array()))
22822 swap(*(m_data.m_value.array), other);
22826 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(array_t&) with ", type_name()),
this));
22835 if (JSON_HEDLEY_LIKELY(is_object()))
22838 swap(*(m_data.m_value.object), other);
22842 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(object_t&) with ", type_name()),
this));
22851 if (JSON_HEDLEY_LIKELY(is_string()))
22854 swap(*(m_data.m_value.string), other);
22858 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(string_t&) with ", type_name()),
this));
22867 if (JSON_HEDLEY_LIKELY(is_binary()))
22870 swap(*(m_data.m_value.binary), other);
22874 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(binary_t&) with ", type_name()),
this));
22880 void swap(
typename binary_t::container_type& other)
22883 if (JSON_HEDLEY_LIKELY(is_binary()))
22886 swap(*(m_data.m_value.binary), other);
22890 JSON_THROW(type_error::create(310, detail::concat(
"cannot use swap(binary_t::container_type&) with ", type_name()),
this));
22905#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22906 const auto lhs_type = lhs.type(); \
22907 const auto rhs_type = rhs.type(); \
22909 if (lhs_type == rhs_type) \
22911 switch (lhs_type) \
22913 case value_t::array: \
22914 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22916 case value_t::object: \
22917 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22919 case value_t::null: \
22920 return (null_result); \
22922 case value_t::string: \
22923 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22925 case value_t::boolean: \
22926 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22928 case value_t::number_integer: \
22929 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22931 case value_t::number_unsigned: \
22932 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22934 case value_t::number_float: \
22935 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22937 case value_t::binary: \
22938 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22940 case value_t::discarded: \
22942 return (unordered_result); \
22945 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22947 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22949 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22951 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22953 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22955 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22957 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22959 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22961 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22963 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22965 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22967 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22969 else if(compares_unordered(lhs, rhs))\
22971 return (unordered_result);\
22974 return (default_result);
22976 JSON_PRIVATE_UNLESS_TESTED:
22982 static bool compares_unordered(const_reference lhs, const_reference rhs,
bool inverse =
false) noexcept
22984 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22985 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22989#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22990 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22992 static_cast<void>(inverse);
22993 return lhs.is_discarded() || rhs.is_discarded();
22998 bool compares_unordered(const_reference rhs,
bool inverse =
false) const noexcept
23000 return compares_unordered(*
this, rhs, inverse);
23004#if JSON_HAS_THREE_WAY_COMPARISON
23007 bool operator==(const_reference rhs)
const noexcept
23010#pragma GCC diagnostic push
23011#pragma GCC diagnostic ignored "-Wfloat-equal"
23013 const_reference lhs = *
this;
23014 JSON_IMPLEMENT_OPERATOR( ==,
true,
false,
false)
23016#pragma GCC diagnostic pop
23022 template<
typename ScalarType>
23023 requires std::is_scalar_v<ScalarType>
23024 bool operator==(ScalarType rhs)
const noexcept
23031 bool operator!=(const_reference rhs)
const noexcept
23033 if (compares_unordered(rhs,
true))
23037 return !operator==(rhs);
23042 std::partial_ordering operator<=>(const_reference rhs)
const noexcept
23044 const_reference lhs = *
this;
23047 JSON_IMPLEMENT_OPERATOR(<=>,
23048 std::partial_ordering::equivalent,
23049 std::partial_ordering::unordered,
23050 lhs_type <=> rhs_type)
23055 template<
typename ScalarType>
23056 requires std::is_scalar_v<ScalarType>
23057 std::partial_ordering operator<=>(ScalarType rhs)
const noexcept
23062#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23068 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23069 bool operator<=(const_reference rhs)
const noexcept
23071 if (compares_unordered(rhs,
true))
23075 return !(rhs < *
this);
23080 template<
typename ScalarType>
23081 requires std::is_scalar_v<ScalarType>
23082 bool operator<=(ScalarType rhs)
const noexcept
23089 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23090 bool operator>=(const_reference rhs)
const noexcept
23092 if (compares_unordered(rhs,
true))
23096 return !(*
this < rhs);
23101 template<
typename ScalarType>
23102 requires std::is_scalar_v<ScalarType>
23103 bool operator>=(ScalarType rhs)
const noexcept
23111 friend bool operator==(const_reference lhs, const_reference rhs)
noexcept
23114#pragma GCC diagnostic push
23115#pragma GCC diagnostic ignored "-Wfloat-equal"
23117 JSON_IMPLEMENT_OPERATOR( ==,
true,
false,
false)
23119#pragma GCC diagnostic pop
23125 template<
typename ScalarType,
typename std::enable_if<
23126 std::is_scalar<ScalarType>::value,
int>::type = 0>
23127 friend bool operator==(const_reference lhs, ScalarType rhs)
noexcept
23134 template<
typename ScalarType,
typename std::enable_if<
23135 std::is_scalar<ScalarType>::value,
int>::type = 0>
23136 friend bool operator==(ScalarType lhs, const_reference rhs)
noexcept
23143 friend bool operator!=(const_reference lhs, const_reference rhs)
noexcept
23145 if (compares_unordered(lhs, rhs,
true))
23149 return !(lhs == rhs);
23154 template<
typename ScalarType,
typename std::enable_if<
23155 std::is_scalar<ScalarType>::value,
int>::type = 0>
23156 friend bool operator!=(const_reference lhs, ScalarType rhs)
noexcept
23163 template<
typename ScalarType,
typename std::enable_if<
23164 std::is_scalar<ScalarType>::value,
int>::type = 0>
23165 friend bool operator!=(ScalarType lhs, const_reference rhs)
noexcept
23172 friend bool operator<(const_reference lhs, const_reference rhs)
noexcept
23177 JSON_IMPLEMENT_OPERATOR( <,
false,
false,
operator<(lhs_type, rhs_type))
23182 template<
typename ScalarType,
typename std::enable_if<
23183 std::is_scalar<ScalarType>::value,
int>::type = 0>
23184 friend bool operator<(const_reference lhs, ScalarType rhs)
noexcept
23191 template<
typename ScalarType,
typename std::enable_if<
23192 std::is_scalar<ScalarType>::value,
int>::type = 0>
23193 friend bool operator<(ScalarType lhs, const_reference rhs)
noexcept
23200 friend bool operator<=(const_reference lhs, const_reference rhs)
noexcept
23202 if (compares_unordered(lhs, rhs,
true))
23206 return !(rhs < lhs);
23211 template<
typename ScalarType,
typename std::enable_if<
23212 std::is_scalar<ScalarType>::value,
int>::type = 0>
23213 friend bool operator<=(const_reference lhs, ScalarType rhs)
noexcept
23220 template<
typename ScalarType,
typename std::enable_if<
23221 std::is_scalar<ScalarType>::value,
int>::type = 0>
23222 friend bool operator<=(ScalarType lhs, const_reference rhs)
noexcept
23229 friend bool operator>(const_reference lhs, const_reference rhs)
noexcept
23232 if (compares_unordered(lhs, rhs))
23236 return !(lhs <= rhs);
23241 template<
typename ScalarType,
typename std::enable_if<
23242 std::is_scalar<ScalarType>::value,
int>::type = 0>
23243 friend bool operator>(const_reference lhs, ScalarType rhs)
noexcept
23250 template<
typename ScalarType,
typename std::enable_if<
23251 std::is_scalar<ScalarType>::value,
int>::type = 0>
23252 friend bool operator>(ScalarType lhs, const_reference rhs)
noexcept
23259 friend bool operator>=(const_reference lhs, const_reference rhs)
noexcept
23261 if (compares_unordered(lhs, rhs,
true))
23265 return !(lhs < rhs);
23270 template<
typename ScalarType,
typename std::enable_if<
23271 std::is_scalar<ScalarType>::value,
int>::type = 0>
23272 friend bool operator>=(const_reference lhs, ScalarType rhs)
noexcept
23279 template<
typename ScalarType,
typename std::enable_if<
23280 std::is_scalar<ScalarType>::value,
int>::type = 0>
23281 friend bool operator>=(ScalarType lhs, const_reference rhs)
noexcept
23287#undef JSON_IMPLEMENT_OPERATOR
23300 friend std::ostream& operator<<(std::ostream& o,
const basic_json& j)
23303 const bool pretty_print = o.width() > 0;
23304 const auto indentation = pretty_print ? o.width() : 0;
23311 s.dump(j, pretty_print,
false,
static_cast<unsigned int>(indentation));
23321 JSON_HEDLEY_DEPRECATED_FOR(3.0.0,
operator<<(std::ostream&,
const basic_json&))
23322 friend std::ostream& operator>>(
const basic_json& j, std::ostream& o)
23338 template<
typename InputType>
23339 JSON_HEDLEY_WARN_UNUSED_RESULT
23341 const parser_callback_t cb =
nullptr,
23342 const bool allow_exceptions =
true,
23343 const bool ignore_comments =
false)
23346 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(
true, result);
23352 template<
typename IteratorType>
23353 JSON_HEDLEY_WARN_UNUSED_RESULT
23356 const parser_callback_t cb =
nullptr,
23357 const bool allow_exceptions =
true,
23358 const bool ignore_comments =
false)
23361 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(
true, result);
23365 JSON_HEDLEY_WARN_UNUSED_RESULT
23366 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23368 const parser_callback_t cb =
nullptr,
23369 const bool allow_exceptions =
true,
23370 const bool ignore_comments =
false)
23373 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(
true, result);
23379 template<
typename InputType>
23380 static bool accept(InputType&& i,
23381 const bool ignore_comments =
false)
23383 return parser(detail::input_adapter(std::forward<InputType>(i)),
nullptr,
false, ignore_comments).accept(
true);
23388 template<
typename IteratorType>
23389 static bool accept(IteratorType first, IteratorType last,
23390 const bool ignore_comments =
false)
23392 return parser(detail::input_adapter(std::move(first), std::move(last)),
nullptr,
false, ignore_comments).accept(
true);
23395 JSON_HEDLEY_WARN_UNUSED_RESULT
23396 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23398 const bool ignore_comments =
false)
23400 return parser(i.get(),
nullptr,
false, ignore_comments).accept(
true);
23405 template <
typename InputType,
typename SAX>
23406 JSON_HEDLEY_NON_NULL(2)
23407 static
bool sax_parse(InputType&& i, SAX* sax,
23408 input_format_t format = input_format_t::json,
23409 const
bool strict = true,
23410 const
bool ignore_comments = false)
23412 auto ia = detail::input_adapter(std::forward<InputType>(i));
23413 return format == input_format_t::json
23414 ? parser(std::move(ia),
nullptr,
true, ignore_comments).sax_parse(sax, strict)
23420 template<
class IteratorType,
class SAX>
23421 JSON_HEDLEY_NON_NULL(3)
23422 static
bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23424 const
bool strict = true,
23425 const
bool ignore_comments = false)
23427 auto ia = detail::input_adapter(std::move(first), std::move(last));
23428 return format == input_format_t::json
23429 ? parser(std::move(ia),
nullptr,
true, ignore_comments).sax_parse(sax, strict)
23438 template <
typename SAX>
23439 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23440 JSON_HEDLEY_NON_NULL(2)
23441 static
bool sax_parse(
detail::span_input_adapter&& i, SAX* sax,
23443 const
bool strict = true,
23444 const
bool ignore_comments = false)
23447 return format == input_format_t::json
23449 ? parser(std::move(ia),
nullptr,
true, ignore_comments).sax_parse(sax, strict)
23460 JSON_HEDLEY_DEPRECATED_FOR(3.0.0,
operator>>(std::istream&,
basic_json&))
23463 return operator>>(i, j);
23470 parser(detail::input_adapter(i)).parse(
false, j);
23482 JSON_HEDLEY_RETURNS_NON_NULL
23485 switch (m_data.m_type)
23487 case value_t::null:
23489 case value_t::object:
23491 case value_t::array:
23493 case value_t::string:
23495 case value_t::boolean:
23497 case value_t::binary:
23499 case value_t::discarded:
23500 return "discarded";
23501 case value_t::number_integer:
23502 case value_t::number_unsigned:
23503 case value_t::number_float:
23509 JSON_PRIVATE_UNLESS_TESTED:
23517 value_t m_type = value_t::null;
23520 json_value m_value = {};
23522 data(
const value_t v)
23523 : m_type(v), m_value(v)
23530 m_value.array = create<array_t>(cnt, val);
23533 data() noexcept = default;
23534 data(data&&) noexcept = default;
23535 data(const data&) noexcept = delete;
23536 data& operator=(data&&) noexcept = delete;
23537 data& operator=(const data&) noexcept = delete;
23541 m_value.destroy(m_type);
23547#if JSON_DIAGNOSTICS
23564 std::vector<std::uint8_t> result;
23565 to_cbor(j, result);
23573 binary_writer<std::uint8_t>(o).write_cbor(j);
23580 binary_writer<char>(o).write_cbor(j);
23587 std::vector<std::uint8_t> result;
23588 to_msgpack(j, result);
23596 binary_writer<std::uint8_t>(o).write_msgpack(j);
23603 binary_writer<char>(o).write_msgpack(j);
23609 const bool use_size =
false,
23610 const bool use_type =
false)
23612 std::vector<std::uint8_t> result;
23613 to_ubjson(j, result, use_size, use_type);
23620 const bool use_size =
false,
const bool use_type =
false)
23622 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23628 const bool use_size =
false,
const bool use_type =
false)
23630 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23636 const bool use_size =
false,
23637 const bool use_type =
false)
23639 std::vector<std::uint8_t> result;
23640 to_bjdata(j, result, use_size, use_type);
23647 const bool use_size =
false,
const bool use_type =
false)
23649 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type,
true,
true);
23655 const bool use_size =
false,
const bool use_type =
false)
23657 binary_writer<char>(o).write_ubjson(j, use_size, use_type,
true,
true);
23664 std::vector<std::uint8_t> result;
23665 to_bson(j, result);
23673 binary_writer<std::uint8_t>(o).write_bson(j);
23680 binary_writer<char>(o).write_bson(j);
23685 template<
typename InputType>
23686 JSON_HEDLEY_WARN_UNUSED_RESULT
23688 const bool strict =
true,
23689 const bool allow_exceptions =
true,
23694 auto ia = detail::input_adapter(std::forward<InputType>(i));
23695 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23696 return res ? result :
basic_json(value_t::discarded);
23701 template<
typename IteratorType>
23702 JSON_HEDLEY_WARN_UNUSED_RESULT
23704 const bool strict =
true,
23705 const bool allow_exceptions =
true,
23710 auto ia = detail::input_adapter(std::move(first), std::move(last));
23711 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23712 return res ? result :
basic_json(value_t::discarded);
23715 template<
typename T>
23716 JSON_HEDLEY_WARN_UNUSED_RESULT
23717 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23718 static basic_json from_cbor(
const T* ptr, std::size_t len,
23719 const bool strict =
true,
23720 const bool allow_exceptions =
true,
23721 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23723 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23726 JSON_HEDLEY_WARN_UNUSED_RESULT
23727 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23729 const bool strict =
true,
23730 const bool allow_exceptions =
true,
23731 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23737 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23738 return res ? result :
basic_json(value_t::discarded);
23743 template<
typename InputType>
23744 JSON_HEDLEY_WARN_UNUSED_RESULT
23746 const bool strict =
true,
23747 const bool allow_exceptions =
true)
23751 auto ia = detail::input_adapter(std::forward<InputType>(i));
23752 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23753 return res ? result :
basic_json(value_t::discarded);
23758 template<
typename IteratorType>
23759 JSON_HEDLEY_WARN_UNUSED_RESULT
23761 const bool strict =
true,
23762 const bool allow_exceptions =
true)
23766 auto ia = detail::input_adapter(std::move(first), std::move(last));
23767 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23768 return res ? result :
basic_json(value_t::discarded);
23771 template<
typename T>
23772 JSON_HEDLEY_WARN_UNUSED_RESULT
23773 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23774 static basic_json from_msgpack(
const T* ptr, std::size_t len,
23775 const bool strict =
true,
23776 const bool allow_exceptions =
true)
23778 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23781 JSON_HEDLEY_WARN_UNUSED_RESULT
23782 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23784 const bool strict =
true,
23785 const bool allow_exceptions =
true)
23791 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23792 return res ? result :
basic_json(value_t::discarded);
23797 template<
typename InputType>
23798 JSON_HEDLEY_WARN_UNUSED_RESULT
23800 const bool strict =
true,
23801 const bool allow_exceptions =
true)
23805 auto ia = detail::input_adapter(std::forward<InputType>(i));
23806 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23807 return res ? result :
basic_json(value_t::discarded);
23812 template<
typename IteratorType>
23813 JSON_HEDLEY_WARN_UNUSED_RESULT
23815 const bool strict =
true,
23816 const bool allow_exceptions =
true)
23820 auto ia = detail::input_adapter(std::move(first), std::move(last));
23821 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23822 return res ? result :
basic_json(value_t::discarded);
23825 template<
typename T>
23826 JSON_HEDLEY_WARN_UNUSED_RESULT
23827 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23828 static basic_json from_ubjson(
const T* ptr, std::size_t len,
23829 const bool strict =
true,
23830 const bool allow_exceptions =
true)
23832 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23835 JSON_HEDLEY_WARN_UNUSED_RESULT
23836 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23838 const bool strict =
true,
23839 const bool allow_exceptions =
true)
23845 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23846 return res ? result :
basic_json(value_t::discarded);
23851 template<
typename InputType>
23852 JSON_HEDLEY_WARN_UNUSED_RESULT
23854 const bool strict =
true,
23855 const bool allow_exceptions =
true)
23859 auto ia = detail::input_adapter(std::forward<InputType>(i));
23860 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23861 return res ? result :
basic_json(value_t::discarded);
23866 template<
typename IteratorType>
23867 JSON_HEDLEY_WARN_UNUSED_RESULT
23869 const bool strict =
true,
23870 const bool allow_exceptions =
true)
23874 auto ia = detail::input_adapter(std::move(first), std::move(last));
23875 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23876 return res ? result :
basic_json(value_t::discarded);
23881 template<
typename InputType>
23882 JSON_HEDLEY_WARN_UNUSED_RESULT
23884 const bool strict =
true,
23885 const bool allow_exceptions =
true)
23889 auto ia = detail::input_adapter(std::forward<InputType>(i));
23890 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23891 return res ? result :
basic_json(value_t::discarded);
23896 template<
typename IteratorType>
23897 JSON_HEDLEY_WARN_UNUSED_RESULT
23899 const bool strict =
true,
23900 const bool allow_exceptions =
true)
23904 auto ia = detail::input_adapter(std::move(first), std::move(last));
23905 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23906 return res ? result :
basic_json(value_t::discarded);
23909 template<
typename T>
23910 JSON_HEDLEY_WARN_UNUSED_RESULT
23911 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23912 static basic_json from_bson(
const T* ptr, std::size_t len,
23913 const bool strict =
true,
23914 const bool allow_exceptions =
true)
23916 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23919 JSON_HEDLEY_WARN_UNUSED_RESULT
23920 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23922 const bool strict =
true,
23923 const bool allow_exceptions =
true)
23929 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23930 return res ? result :
basic_json(value_t::discarded);
23948 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23950 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23952 return ptr.get_unchecked(
this);
23962 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23964 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
const
23966 return ptr.get_unchecked(
this);
23976 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23978 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23980 return ptr.get_checked(
this);
23990 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value,
int> = 0>
23992 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
const
23994 return ptr.get_checked(
this);
24028 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24030 const auto get_op = [](
const std::string & op)
24034 return patch_operations::add;
24036 if (op ==
"remove")
24038 return patch_operations::remove;
24040 if (op ==
"replace")
24042 return patch_operations::replace;
24046 return patch_operations::move;
24050 return patch_operations::copy;
24054 return patch_operations::test;
24057 return patch_operations::invalid;
24072 if (top_pointer != ptr)
24074 result.
at(top_pointer);
24078 const auto last_path = ptr.
back();
24083 switch (parent.m_data.m_type)
24085 case value_t::null:
24086 case value_t::object:
24089 parent[last_path] = val;
24093 case value_t::array:
24095 if (last_path ==
"-")
24102 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24103 if (JSON_HEDLEY_UNLIKELY(idx > parent.
size()))
24106 JSON_THROW(out_of_range::create(401, detail::concat(
"array index ", std::to_string(idx),
" is out of range"), &parent));
24116 case value_t::string:
24117 case value_t::boolean:
24118 case value_t::number_integer:
24119 case value_t::number_unsigned:
24120 case value_t::number_float:
24121 case value_t::binary:
24122 case value_t::discarded:
24124 JSON_ASSERT(
false);
24129 const auto operation_remove = [
this, & result](
json_pointer & ptr)
24132 const auto last_path = ptr.
back();
24140 auto it = parent.
find(last_path);
24141 if (JSON_HEDLEY_LIKELY(it != parent.
end()))
24147 JSON_THROW(out_of_range::create(403, detail::concat(
"key '", last_path,
"' not found"),
this));
24153 parent.
erase(json_pointer::template array_index<basic_json_t>(last_path));
24158 if (JSON_HEDLEY_UNLIKELY(!json_patch.
is_array()))
24160 JSON_THROW(parse_error::create(104, 0,
"JSON patch must be an array of objects", &json_patch));
24164 for (
const auto& val : json_patch)
24167 const auto get_value = [&val](
const std::string & op,
24168 const std::string & member,
24172 auto it = val.m_data.m_value.object->find(member);
24175 const auto error_msg = (op ==
"op") ?
"operation" : detail::concat(
"operation '", op,
'\'');
24178 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24181 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg,
" must have member '", member,
"'"), &val));
24185 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24188 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg,
" must have string member '", member,
"'"), &val));
24196 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24198 JSON_THROW(parse_error::create(104, 0,
"JSON patch must be an array of objects", &val));
24202 const auto op = get_value(
"op",
"op",
true).template get<std::string>();
24203 const auto path = get_value(op,
"path",
true).template get<std::string>();
24206 switch (get_op(op))
24208 case patch_operations::add:
24210 operation_add(ptr, get_value(
"add",
"value",
false));
24214 case patch_operations::remove:
24216 operation_remove(ptr);
24220 case patch_operations::replace:
24223 result.
at(ptr) = get_value(
"replace",
"value",
false);
24227 case patch_operations::move:
24229 const auto from_path = get_value(
"move",
"from",
true).template get<std::string>();
24239 operation_remove(from_ptr);
24240 operation_add(ptr, v);
24244 case patch_operations::copy:
24246 const auto from_path = get_value(
"copy",
"from",
true).template get<std::string>();
24255 operation_add(ptr, v);
24259 case patch_operations::test:
24261 bool success =
false;
24266 success = (result.
at(ptr) == get_value(
"test",
"value",
false));
24274 if (JSON_HEDLEY_UNLIKELY(!success))
24276 JSON_THROW(other_error::create(501, detail::concat(
"unsuccessful: ", val.dump()), &val));
24282 case patch_operations::invalid:
24287 JSON_THROW(parse_error::create(105, 0, detail::concat(
"operation value '", op,
"' is invalid"), &val));
24304 JSON_HEDLEY_WARN_UNUSED_RESULT
24306 const std::string& path =
"")
24312 if (source == target)
24317 if (source.
type() != target.
type())
24322 {
"op",
"replace"}, {
"path", path}, {
"value", target}
24327 switch (source.
type())
24329 case value_t::array:
24333 while (i < source.
size() && i < target.
size())
24336 auto temp_diff = diff(source[i], target[i], detail::concat(path,
'/', std::to_string(i)));
24337 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
24346 while (i < source.
size())
24350 result.
insert(result.
begin() + end_index, object(
24353 {
"path", detail::concat(path,
'/', std::to_string(i))}
24359 while (i < target.
size())
24364 {
"path", detail::concat(path,
"/-")},
24365 {
"value", target[i]}
24373 case value_t::object:
24376 for (
auto it = source.
cbegin(); it != source.
cend(); ++it)
24379 const auto path_key = detail::concat(path,
'/',
detail::escape(it.key()));
24381 if (target.
find(it.key()) != target.
end())
24384 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24385 result.
insert(result.
end(), temp_diff.begin(), temp_diff.end());
24392 {
"op",
"remove"}, {
"path", path_key}
24398 for (
auto it = target.
cbegin(); it != target.
cend(); ++it)
24400 if (source.
find(it.key()) == source.
end())
24403 const auto path_key = detail::concat(path,
'/',
detail::escape(it.key()));
24406 {
"op",
"add"}, {
"path", path_key},
24407 {
"value", it.value()}
24415 case value_t::null:
24416 case value_t::string:
24417 case value_t::boolean:
24418 case value_t::number_integer:
24419 case value_t::number_unsigned:
24420 case value_t::number_float:
24421 case value_t::binary:
24422 case value_t::discarded:
24428 {
"op",
"replace"}, {
"path", path}, {
"value", target}
24455 for (
auto it = apply_patch.
begin(); it != apply_patch.
end(); ++it)
24457 if (it.value().is_null())
24463 operator[](it.key()).merge_patch(it.value());
24469 *
this = apply_patch;
24478NLOHMANN_BASIC_JSON_TPL_DECLARATION
24479std::string to_string(
const NLOHMANN_BASIC_JSON_TPL& j)
24484inline namespace literals
24486inline namespace json_literals
24491JSON_HEDLEY_NON_NULL(1)
24492#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24493 inline nlohmann::json
operator ""_json(
const char* s, std::size_t n)
24495 inline nlohmann::json
operator "" _json(
const char* s, std::size_t n)
24498 return nlohmann::json::parse(s, s + n);
24503JSON_HEDLEY_NON_NULL(1)
24504#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24505 inline nlohmann::json::json_pointer
operator ""_json_pointer(
const char* s, std::size_t n)
24507 inline nlohmann::json::json_pointer
operator "" _json_pointer(
const char* s, std::size_t n)
24510 return nlohmann::json::json_pointer(std::string(s, n));
24515NLOHMANN_JSON_NAMESPACE_END
24526NLOHMANN_BASIC_JSON_TPL_DECLARATION
24527struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
24529 std::size_t operator()(
const nlohmann::NLOHMANN_BASIC_JSON_TPL& j)
const
24531 return nlohmann::detail::hash(j);
24537struct less< ::nlohmann::detail::value_t>
24544 ::nlohmann::detail::value_t rhs)
const noexcept
24546#if JSON_HAS_THREE_WAY_COMPARISON
24547 return std::is_lt(lhs <=> rhs);
24549 return ::nlohmann::detail::operator<(lhs, rhs);
24555#ifndef JSON_HAS_CPP_20
24559NLOHMANN_BASIC_JSON_TPL_DECLARATION
24560inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2)
noexcept(
24561 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&
24562 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24571#if JSON_USE_GLOBAL_UDLS
24572 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24573 using nlohmann::literals::json_literals::operator
""_json;
24574 using nlohmann::literals::json_literals::operator
""_json_pointer;
24576 using nlohmann::literals::json_literals::operator
"" _json;
24577 using nlohmann::literals::json_literals::operator
"" _json_pointer;
24593#if defined(__clang__)
24594 #pragma clang diagnostic pop
24599#undef JSON_INTERNAL_CATCH
24601#undef JSON_PRIVATE_UNLESS_TESTED
24602#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24603#undef NLOHMANN_BASIC_JSON_TPL
24604#undef JSON_EXPLICIT
24605#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24606#undef JSON_INLINE_VARIABLE
24607#undef JSON_NO_UNIQUE_ADDRESS
24608#undef JSON_DISABLE_ENUM_SERIALIZATION
24609#undef JSON_USE_GLOBAL_UDLS
24611#ifndef JSON_TEST_KEEP_MACROS
24614 #undef JSON_HAS_CPP_11
24615 #undef JSON_HAS_CPP_14
24616 #undef JSON_HAS_CPP_17
24617 #undef JSON_HAS_CPP_20
24618 #undef JSON_HAS_FILESYSTEM
24619 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24620 #undef JSON_HAS_THREE_WAY_COMPARISON
24621 #undef JSON_HAS_RANGES
24622 #undef JSON_HAS_STATIC_RTTI
24623 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24637#undef JSON_HEDLEY_ALWAYS_INLINE
24638#undef JSON_HEDLEY_ARM_VERSION
24639#undef JSON_HEDLEY_ARM_VERSION_CHECK
24640#undef JSON_HEDLEY_ARRAY_PARAM
24641#undef JSON_HEDLEY_ASSUME
24642#undef JSON_HEDLEY_BEGIN_C_DECLS
24643#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24644#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24645#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24646#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24647#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24648#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24649#undef JSON_HEDLEY_CLANG_HAS_WARNING
24650#undef JSON_HEDLEY_COMPCERT_VERSION
24651#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24652#undef JSON_HEDLEY_CONCAT
24653#undef JSON_HEDLEY_CONCAT3
24654#undef JSON_HEDLEY_CONCAT3_EX
24655#undef JSON_HEDLEY_CONCAT_EX
24656#undef JSON_HEDLEY_CONST
24657#undef JSON_HEDLEY_CONSTEXPR
24658#undef JSON_HEDLEY_CONST_CAST
24659#undef JSON_HEDLEY_CPP_CAST
24660#undef JSON_HEDLEY_CRAY_VERSION
24661#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24662#undef JSON_HEDLEY_C_DECL
24663#undef JSON_HEDLEY_DEPRECATED
24664#undef JSON_HEDLEY_DEPRECATED_FOR
24665#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24666#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24667#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24668#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24669#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24670#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24671#undef JSON_HEDLEY_DIAGNOSTIC_POP
24672#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24673#undef JSON_HEDLEY_DMC_VERSION
24674#undef JSON_HEDLEY_DMC_VERSION_CHECK
24675#undef JSON_HEDLEY_EMPTY_BASES
24676#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24677#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24678#undef JSON_HEDLEY_END_C_DECLS
24679#undef JSON_HEDLEY_FLAGS
24680#undef JSON_HEDLEY_FLAGS_CAST
24681#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24682#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24683#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24684#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24685#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24686#undef JSON_HEDLEY_GCC_HAS_FEATURE
24687#undef JSON_HEDLEY_GCC_HAS_WARNING
24688#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24689#undef JSON_HEDLEY_GCC_VERSION
24690#undef JSON_HEDLEY_GCC_VERSION_CHECK
24691#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24692#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24693#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24694#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24695#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24696#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24697#undef JSON_HEDLEY_GNUC_HAS_WARNING
24698#undef JSON_HEDLEY_GNUC_VERSION
24699#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24700#undef JSON_HEDLEY_HAS_ATTRIBUTE
24701#undef JSON_HEDLEY_HAS_BUILTIN
24702#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24703#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24704#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24705#undef JSON_HEDLEY_HAS_EXTENSION
24706#undef JSON_HEDLEY_HAS_FEATURE
24707#undef JSON_HEDLEY_HAS_WARNING
24708#undef JSON_HEDLEY_IAR_VERSION
24709#undef JSON_HEDLEY_IAR_VERSION_CHECK
24710#undef JSON_HEDLEY_IBM_VERSION
24711#undef JSON_HEDLEY_IBM_VERSION_CHECK
24712#undef JSON_HEDLEY_IMPORT
24713#undef JSON_HEDLEY_INLINE
24714#undef JSON_HEDLEY_INTEL_CL_VERSION
24715#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24716#undef JSON_HEDLEY_INTEL_VERSION
24717#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24718#undef JSON_HEDLEY_IS_CONSTANT
24719#undef JSON_HEDLEY_IS_CONSTEXPR_
24720#undef JSON_HEDLEY_LIKELY
24721#undef JSON_HEDLEY_MALLOC
24722#undef JSON_HEDLEY_MCST_LCC_VERSION
24723#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24724#undef JSON_HEDLEY_MESSAGE
24725#undef JSON_HEDLEY_MSVC_VERSION
24726#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24727#undef JSON_HEDLEY_NEVER_INLINE
24728#undef JSON_HEDLEY_NON_NULL
24729#undef JSON_HEDLEY_NO_ESCAPE
24730#undef JSON_HEDLEY_NO_RETURN
24731#undef JSON_HEDLEY_NO_THROW
24732#undef JSON_HEDLEY_NULL
24733#undef JSON_HEDLEY_PELLES_VERSION
24734#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24735#undef JSON_HEDLEY_PGI_VERSION
24736#undef JSON_HEDLEY_PGI_VERSION_CHECK
24737#undef JSON_HEDLEY_PREDICT
24738#undef JSON_HEDLEY_PRINTF_FORMAT
24739#undef JSON_HEDLEY_PRIVATE
24740#undef JSON_HEDLEY_PUBLIC
24741#undef JSON_HEDLEY_PURE
24742#undef JSON_HEDLEY_REINTERPRET_CAST
24743#undef JSON_HEDLEY_REQUIRE
24744#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24745#undef JSON_HEDLEY_REQUIRE_MSG
24746#undef JSON_HEDLEY_RESTRICT
24747#undef JSON_HEDLEY_RETURNS_NON_NULL
24748#undef JSON_HEDLEY_SENTINEL
24749#undef JSON_HEDLEY_STATIC_ASSERT
24750#undef JSON_HEDLEY_STATIC_CAST
24751#undef JSON_HEDLEY_STRINGIFY
24752#undef JSON_HEDLEY_STRINGIFY_EX
24753#undef JSON_HEDLEY_SUNPRO_VERSION
24754#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24755#undef JSON_HEDLEY_TINYC_VERSION
24756#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24757#undef JSON_HEDLEY_TI_ARMCL_VERSION
24758#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24759#undef JSON_HEDLEY_TI_CL2000_VERSION
24760#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24761#undef JSON_HEDLEY_TI_CL430_VERSION
24762#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24763#undef JSON_HEDLEY_TI_CL6X_VERSION
24764#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24765#undef JSON_HEDLEY_TI_CL7X_VERSION
24766#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24767#undef JSON_HEDLEY_TI_CLPRU_VERSION
24768#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24769#undef JSON_HEDLEY_TI_VERSION
24770#undef JSON_HEDLEY_TI_VERSION_CHECK
24771#undef JSON_HEDLEY_UNAVAILABLE
24772#undef JSON_HEDLEY_UNLIKELY
24773#undef JSON_HEDLEY_UNPREDICTABLE
24774#undef JSON_HEDLEY_UNREACHABLE
24775#undef JSON_HEDLEY_UNREACHABLE_RETURN
24776#undef JSON_HEDLEY_VERSION
24777#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24778#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24779#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24780#undef JSON_HEDLEY_VERSION_ENCODE
24781#undef JSON_HEDLEY_WARNING
24782#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24783#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24784#undef JSON_HEDLEY_FALL_THROUGH
24822#ifndef CPPHTTPLIB_HTTPLIB_H
24823#define CPPHTTPLIB_HTTPLIB_H
24825#define CPPHTTPLIB_VERSION "0.15.3"
24831#ifndef CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND
24832#define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 5
24835#ifndef CPPHTTPLIB_KEEPALIVE_MAX_COUNT
24836#define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 5
24839#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND
24840#define CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND 300
24843#ifndef CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND
24844#define CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND 0
24847#ifndef CPPHTTPLIB_READ_TIMEOUT_SECOND
24848#define CPPHTTPLIB_READ_TIMEOUT_SECOND 5
24851#ifndef CPPHTTPLIB_READ_TIMEOUT_USECOND
24852#define CPPHTTPLIB_READ_TIMEOUT_USECOND 0
24855#ifndef CPPHTTPLIB_WRITE_TIMEOUT_SECOND
24856#define CPPHTTPLIB_WRITE_TIMEOUT_SECOND 5
24859#ifndef CPPHTTPLIB_WRITE_TIMEOUT_USECOND
24860#define CPPHTTPLIB_WRITE_TIMEOUT_USECOND 0
24863#ifndef CPPHTTPLIB_IDLE_INTERVAL_SECOND
24864#define CPPHTTPLIB_IDLE_INTERVAL_SECOND 0
24867#ifndef CPPHTTPLIB_IDLE_INTERVAL_USECOND
24869#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 10000
24871#define CPPHTTPLIB_IDLE_INTERVAL_USECOND 0
24875#ifndef CPPHTTPLIB_REQUEST_URI_MAX_LENGTH
24876#define CPPHTTPLIB_REQUEST_URI_MAX_LENGTH 8192
24879#ifndef CPPHTTPLIB_HEADER_MAX_LENGTH
24880#define CPPHTTPLIB_HEADER_MAX_LENGTH 8192
24883#ifndef CPPHTTPLIB_REDIRECT_MAX_COUNT
24884#define CPPHTTPLIB_REDIRECT_MAX_COUNT 20
24887#ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT
24888#define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 1024
24891#ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH
24892#define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits<size_t>::max)())
24895#ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH
24896#define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192
24899#ifndef CPPHTTPLIB_RANGE_MAX_COUNT
24900#define CPPHTTPLIB_RANGE_MAX_COUNT 1024
24903#ifndef CPPHTTPLIB_TCP_NODELAY
24904#define CPPHTTPLIB_TCP_NODELAY false
24907#ifndef CPPHTTPLIB_RECV_BUFSIZ
24908#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u)
24911#ifndef CPPHTTPLIB_COMPRESSION_BUFSIZ
24912#define CPPHTTPLIB_COMPRESSION_BUFSIZ size_t(16384u)
24915#ifndef CPPHTTPLIB_THREAD_POOL_COUNT
24916#define CPPHTTPLIB_THREAD_POOL_COUNT \
24917 ((std::max)(8u, std::thread::hardware_concurrency() > 0 \
24918 ? std::thread::hardware_concurrency() - 1 \
24922#ifndef CPPHTTPLIB_RECV_FLAGS
24923#define CPPHTTPLIB_RECV_FLAGS 0
24926#ifndef CPPHTTPLIB_SEND_FLAGS
24927#define CPPHTTPLIB_SEND_FLAGS 0
24930#ifndef CPPHTTPLIB_LISTEN_BACKLOG
24931#define CPPHTTPLIB_LISTEN_BACKLOG 5
24939#ifndef _CRT_SECURE_NO_WARNINGS
24940#define _CRT_SECURE_NO_WARNINGS
24943#ifndef _CRT_NONSTDC_NO_DEPRECATE
24944#define _CRT_NONSTDC_NO_DEPRECATE
24947#if defined(_MSC_VER)
24949#error Sorry, Visual Studio versions prior to 2015 are not supported
24952#pragma comment(lib, "ws2_32.lib")
24955using ssize_t = __int64;
24957using ssize_t = long;
24962#define S_ISREG(m) (((m) & S_IFREG) == S_IFREG)
24966#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR)
24974#include <winsock2.h>
24975#include <ws2tcpip.h>
24977#ifndef WSA_FLAG_NO_HANDLE_INHERIT
24978#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
24981using socket_t = SOCKET;
24982#ifdef CPPHTTPLIB_USE_POLL
24983#define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout)
24988#include <arpa/inet.h>
24989#if !defined(_AIX) && !defined(__MVS__)
24990#include <ifaddrs.h>
24993#include <strings.h>
24995#define NI_MAXHOST 1025
25000#include <netinet/in.h>
25004#include <netinet/tcp.h>
25005#ifdef CPPHTTPLIB_USE_POLL
25009#include <pthread.h>
25010#include <sys/mman.h>
25011#include <sys/select.h>
25012#include <sys/socket.h>
25016using socket_t = int;
25017#ifndef INVALID_SOCKET
25018#define INVALID_SOCKET (-1)
25022#include <algorithm>
25028#include <condition_variable>
25031#include <exception>
25034#include <functional>
25046#include <sys/stat.h>
25048#include <unordered_map>
25049#include <unordered_set>
25052#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
25054#include <wincrypt.h>
25059#undef X509_CERT_PAIR
25060#undef X509_EXTENSIONS
25061#undef PKCS7_SIGNER_INFO
25064#pragma comment(lib, "crypt32.lib")
25066#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
25067#include <TargetConditionals.h>
25069#include <CoreFoundation/CoreFoundation.h>
25070#include <Security/Security.h>
25074#include <openssl/err.h>
25075#include <openssl/evp.h>
25076#include <openssl/ssl.h>
25077#include <openssl/x509v3.h>
25079#if defined(_WIN32) && defined(OPENSSL_USE_APPLINK)
25080#include <openssl/applink.c>
25086#if OPENSSL_VERSION_NUMBER < 0x30000000L
25087#error Sorry, OpenSSL versions prior to 3.0.0 are not supported
25092#ifdef CPPHTTPLIB_ZLIB_SUPPORT
25096#ifdef CPPHTTPLIB_BROTLI_SUPPORT
25097#include <brotli/decode.h>
25098#include <brotli/encode.h>
25116template <
class T,
class... Args>
25117typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
25118make_unique(Args &&...args) {
25119 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
25123typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
25124make_unique(std::size_t n) {
25125 typedef typename std::remove_extent<T>::type RT;
25126 return std::unique_ptr<T>(
new RT[n]);
25130 bool operator()(
const std::string &s1,
const std::string &s2)
const {
25131 return std::lexicographical_compare(s1.begin(), s1.end(), s2.begin(),
25133 [](
unsigned char c1,
unsigned char c2) {
25134 return ::tolower(c1) < ::tolower(c2);
25143 explicit scope_exit(std::function<
void(
void)> &&f)
25144 : exit_function(std::move(f)), execute_on_destruction{
true} {}
25147 : exit_function(std::move(rhs.exit_function)),
25148 execute_on_destruction{rhs.execute_on_destruction} {
25153 if (execute_on_destruction) { this->exit_function(); }
25156 void release() { this->execute_on_destruction =
false; }
25160 void operator=(
const scope_exit &) =
delete;
25163 std::function<void(
void)> exit_function;
25164 bool execute_on_destruction;
25171 Continue_100 = 100,
25172 SwitchingProtocol_101 = 101,
25173 Processing_102 = 102,
25174 EarlyHints_103 = 103,
25179 Accepted_202 = 202,
25180 NonAuthoritativeInformation_203 = 203,
25181 NoContent_204 = 204,
25182 ResetContent_205 = 205,
25183 PartialContent_206 = 206,
25184 MultiStatus_207 = 207,
25185 AlreadyReported_208 = 208,
25189 MultipleChoices_300 = 300,
25190 MovedPermanently_301 = 301,
25192 SeeOther_303 = 303,
25193 NotModified_304 = 304,
25194 UseProxy_305 = 305,
25196 TemporaryRedirect_307 = 307,
25197 PermanentRedirect_308 = 308,
25200 BadRequest_400 = 400,
25201 Unauthorized_401 = 401,
25202 PaymentRequired_402 = 402,
25203 Forbidden_403 = 403,
25204 NotFound_404 = 404,
25205 MethodNotAllowed_405 = 405,
25206 NotAcceptable_406 = 406,
25207 ProxyAuthenticationRequired_407 = 407,
25208 RequestTimeout_408 = 408,
25209 Conflict_409 = 409,
25211 LengthRequired_411 = 411,
25212 PreconditionFailed_412 = 412,
25213 PayloadTooLarge_413 = 413,
25214 UriTooLong_414 = 414,
25215 UnsupportedMediaType_415 = 415,
25216 RangeNotSatisfiable_416 = 416,
25217 ExpectationFailed_417 = 417,
25218 ImATeapot_418 = 418,
25219 MisdirectedRequest_421 = 421,
25220 UnprocessableContent_422 = 422,
25222 FailedDependency_424 = 424,
25223 TooEarly_425 = 425,
25224 UpgradeRequired_426 = 426,
25225 PreconditionRequired_428 = 428,
25226 TooManyRequests_429 = 429,
25227 RequestHeaderFieldsTooLarge_431 = 431,
25228 UnavailableForLegalReasons_451 = 451,
25231 InternalServerError_500 = 500,
25232 NotImplemented_501 = 501,
25233 BadGateway_502 = 502,
25234 ServiceUnavailable_503 = 503,
25235 GatewayTimeout_504 = 504,
25236 HttpVersionNotSupported_505 = 505,
25237 VariantAlsoNegotiates_506 = 506,
25238 InsufficientStorage_507 = 507,
25239 LoopDetected_508 = 508,
25240 NotExtended_510 = 510,
25241 NetworkAuthenticationRequired_511 = 511,
25244using Headers = std::multimap<std::string, std::string, detail::ci>;
25246using Params = std::multimap<std::string, std::string>;
25247using Match = std::smatch;
25249using Progress = std::function<bool(uint64_t current, uint64_t total)>;
25252using ResponseHandler = std::function<bool(
const Response &response)>;
25256 std::string content;
25257 std::string filename;
25258 std::string content_type;
25260using MultipartFormDataItems = std::vector<MultipartFormData>;
25261using MultipartFormDataMap = std::multimap<std::string, MultipartFormData>;
25265 DataSink() : os(&sb_), sb_(*
this) {}
25272 std::function<bool(
const char *data,
size_t data_len)> write;
25273 std::function<bool()> is_writable;
25274 std::function<void()> done;
25275 std::function<void(
const Headers &trailer)> done_with_trailer;
25284 std::streamsize xsputn(
const char *s, std::streamsize n)
override {
25285 sink_.write(s,
static_cast<size_t>(n));
25296using ContentProvider =
25297 std::function<bool(
size_t offset,
size_t length,
DataSink &sink)>;
25299using ContentProviderWithoutLength =
25300 std::function<bool(
size_t offset,
DataSink &sink)>;
25302using ContentProviderResourceReleaser = std::function<void(
bool success)>;
25306 ContentProviderWithoutLength provider;
25307 std::string filename;
25308 std::string content_type;
25310using MultipartFormDataProviderItems = std::vector<MultipartFormDataProvider>;
25312using ContentReceiverWithProgress =
25313 std::function<bool(
const char *data,
size_t data_length, uint64_t offset,
25314 uint64_t total_length)>;
25316using ContentReceiver =
25317 std::function<bool(
const char *data,
size_t data_length)>;
25319using MultipartContentHeader =
25324 using Reader = std::function<bool(ContentReceiver receiver)>;
25325 using MultipartReader = std::function<bool(MultipartContentHeader header,
25326 ContentReceiver receiver)>;
25328 ContentReader(Reader reader, MultipartReader multipart_reader)
25329 : reader_(std::move(reader)),
25330 multipart_reader_(std::move(multipart_reader)) {}
25332 bool operator()(MultipartContentHeader header,
25333 ContentReceiver receiver)
const {
25334 return multipart_reader_(std::move(header), std::move(receiver));
25337 bool operator()(ContentReceiver receiver)
const {
25338 return reader_(std::move(receiver));
25342 MultipartReader multipart_reader_;
25345using Range = std::pair<ssize_t, ssize_t>;
25346using Ranges = std::vector<Range>;
25349 std::string method;
25354 std::string remote_addr;
25355 int remote_port = -1;
25356 std::string local_addr;
25357 int local_port = -1;
25360 std::string version;
25361 std::string target;
25363 MultipartFormDataMap files;
25366 std::unordered_map<std::string, std::string> path_params;
25369 ResponseHandler response_handler;
25370 ContentReceiverWithProgress content_receiver;
25372#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
25373 const SSL *ssl =
nullptr;
25376 bool has_header(
const std::string &key)
const;
25377 std::string get_header_value(
const std::string &key,
size_t id = 0)
const;
25378 uint64_t get_header_value_u64(
const std::string &key,
size_t id = 0)
const;
25379 size_t get_header_value_count(
const std::string &key)
const;
25380 void set_header(
const std::string &key,
const std::string &val);
25382 bool has_param(
const std::string &key)
const;
25383 std::string get_param_value(
const std::string &key,
size_t id = 0)
const;
25384 size_t get_param_value_count(
const std::string &key)
const;
25386 bool is_multipart_form_data()
const;
25388 bool has_file(
const std::string &key)
const;
25390 std::vector<MultipartFormData> get_file_values(
const std::string &key)
const;
25393 size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT;
25394 size_t content_length_ = 0;
25395 ContentProvider content_provider_;
25396 bool is_chunked_content_provider_ =
false;
25397 size_t authorization_count_ = 0;
25401 std::string version;
25403 std::string reason;
25406 std::string location;
25408 bool has_header(
const std::string &key)
const;
25409 std::string get_header_value(
const std::string &key,
size_t id = 0)
const;
25410 uint64_t get_header_value_u64(
const std::string &key,
size_t id = 0)
const;
25411 size_t get_header_value_count(
const std::string &key)
const;
25412 void set_header(
const std::string &key,
const std::string &val);
25414 void set_redirect(
const std::string &url,
int status = StatusCode::Found_302);
25415 void set_content(
const char *s,
size_t n,
const std::string &content_type);
25416 void set_content(
const std::string &s,
const std::string &content_type);
25417 void set_content(std::string &&s,
const std::string &content_type);
25419 void set_content_provider(
25420 size_t length,
const std::string &content_type, ContentProvider provider,
25421 ContentProviderResourceReleaser resource_releaser =
nullptr);
25423 void set_content_provider(
25424 const std::string &content_type, ContentProviderWithoutLength provider,
25425 ContentProviderResourceReleaser resource_releaser =
nullptr);
25427 void set_chunked_content_provider(
25428 const std::string &content_type, ContentProviderWithoutLength provider,
25429 ContentProviderResourceReleaser resource_releaser =
nullptr);
25437 if (content_provider_resource_releaser_) {
25438 content_provider_resource_releaser_(content_provider_success_);
25443 size_t content_length_ = 0;
25444 ContentProvider content_provider_;
25445 ContentProviderResourceReleaser content_provider_resource_releaser_;
25446 bool is_chunked_content_provider_ =
false;
25447 bool content_provider_success_ =
false;
25454 virtual bool is_readable()
const = 0;
25455 virtual bool is_writable()
const = 0;
25457 virtual ssize_t read(
char *ptr,
size_t size) = 0;
25458 virtual ssize_t write(
const char *ptr,
size_t size) = 0;
25459 virtual void get_remote_ip_and_port(std::string &ip,
int &port)
const = 0;
25460 virtual void get_local_ip_and_port(std::string &ip,
int &port)
const = 0;
25461 virtual socket_t socket()
const = 0;
25463 template <
typename... Args>
25464 ssize_t write_format(
const char *fmt,
const Args &...args);
25465 ssize_t write(
const char *ptr);
25466 ssize_t write(
const std::string &s);
25474 virtual bool enqueue(std::function<
void()> fn) = 0;
25475 virtual void shutdown() = 0;
25477 virtual void on_idle() {}
25482 explicit ThreadPool(
size_t n,
size_t mqr = 0)
25483 : shutdown_(
false), max_queued_requests_(mqr) {
25485 threads_.emplace_back(
worker(*
this));
25493 bool enqueue(std::function<
void()> fn)
override {
25495 std::unique_lock<std::mutex> lock(mutex_);
25496 if (max_queued_requests_ > 0 && jobs_.size() >= max_queued_requests_) {
25499 jobs_.push_back(std::move(fn));
25502 cond_.notify_one();
25506 void shutdown()
override {
25509 std::unique_lock<std::mutex> lock(mutex_);
25513 cond_.notify_all();
25516 for (
auto &t : threads_) {
25525 void operator()() {
25527 std::function<void()> fn;
25529 std::unique_lock<std::mutex> lock(pool_.mutex_);
25532 lock, [&] {
return !pool_.jobs_.empty() || pool_.shutdown_; });
25534 if (pool_.shutdown_ && pool_.jobs_.empty()) {
break; }
25536 fn = pool_.jobs_.front();
25537 pool_.jobs_.pop_front();
25540 assert(
true ==
static_cast<bool>(fn));
25549 std::vector<std::thread> threads_;
25550 std::list<std::function<void()>> jobs_;
25553 size_t max_queued_requests_ = 0;
25555 std::condition_variable cond_;
25559using Logger = std::function<void(
const Request &,
const Response &)>;
25561using SocketOptions = std::function<void(socket_t sock)>;
25563void default_socket_options(socket_t sock);
25565const char *status_message(
int status);
25567std::string get_bearer_token_auth(
const Request &req);
25576 virtual bool match(
Request &request)
const = 0;
25601 bool match(
Request &request)
const override;
25604 static constexpr char marker =
':';
25608 static constexpr char separator =
'/';
25613 std::vector<std::string> static_fragments_;
25616 std::vector<std::string> param_names_;
25629 RegexMatcher(
const std::string &pattern) : regex_(pattern) {}
25631 bool match(
Request &request)
const override;
25637ssize_t write_headers(
Stream &strm,
const Headers &headers);
25645 using ExceptionHandler =
25646 std::function<void(
const Request &,
Response &, std::exception_ptr ep)>;
25648 enum class HandlerResponse {
25652 using HandlerWithResponse =
25655 using HandlerWithContentReader = std::function<void(
25658 using Expect100ContinueHandler =
25665 virtual bool is_valid()
const;
25667 Server &Get(
const std::string &pattern, Handler handler);
25668 Server &Post(
const std::string &pattern, Handler handler);
25669 Server &Post(
const std::string &pattern, HandlerWithContentReader handler);
25670 Server &Put(
const std::string &pattern, Handler handler);
25671 Server &Put(
const std::string &pattern, HandlerWithContentReader handler);
25672 Server &Patch(
const std::string &pattern, Handler handler);
25673 Server &Patch(
const std::string &pattern, HandlerWithContentReader handler);
25674 Server &Delete(
const std::string &pattern, Handler handler);
25675 Server &Delete(
const std::string &pattern, HandlerWithContentReader handler);
25676 Server &Options(
const std::string &pattern, Handler handler);
25678 bool set_base_dir(
const std::string &dir,
25679 const std::string &mount_point = std::string());
25680 bool set_mount_point(
const std::string &mount_point,
const std::string &dir,
25681 Headers headers = Headers());
25682 bool remove_mount_point(
const std::string &mount_point);
25683 Server &set_file_extension_and_mimetype_mapping(
const std::string &ext,
25684 const std::string &mime);
25685 Server &set_default_file_mimetype(
const std::string &mime);
25686 Server &set_file_request_handler(Handler handler);
25688 template <
class ErrorHandlerFunc>
25689 Server &set_error_handler(ErrorHandlerFunc &&handler) {
25690 return set_error_handler_core(
25691 std::forward<ErrorHandlerFunc>(handler),
25692 std::is_convertible<ErrorHandlerFunc, HandlerWithResponse>{});
25695 Server &set_exception_handler(ExceptionHandler handler);
25696 Server &set_pre_routing_handler(HandlerWithResponse handler);
25697 Server &set_post_routing_handler(Handler handler);
25699 Server &set_expect_100_continue_handler(Expect100ContinueHandler handler);
25700 Server &set_logger(Logger logger);
25702 Server &set_address_family(
int family);
25703 Server &set_tcp_nodelay(
bool on);
25704 Server &set_socket_options(SocketOptions socket_options);
25706 Server &set_default_headers(Headers headers);
25708 set_header_writer(std::function<ssize_t(
Stream &, Headers &)>
const &writer);
25710 Server &set_keep_alive_max_count(
size_t count);
25711 Server &set_keep_alive_timeout(time_t sec);
25713 Server &set_read_timeout(time_t sec, time_t usec = 0);
25714 template <
class Rep,
class Period>
25715 Server &set_read_timeout(
const std::chrono::duration<Rep, Period> &duration);
25717 Server &set_write_timeout(time_t sec, time_t usec = 0);
25718 template <
class Rep,
class Period>
25719 Server &set_write_timeout(
const std::chrono::duration<Rep, Period> &duration);
25721 Server &set_idle_interval(time_t sec, time_t usec = 0);
25722 template <
class Rep,
class Period>
25723 Server &set_idle_interval(
const std::chrono::duration<Rep, Period> &duration);
25725 Server &set_payload_max_length(
size_t length);
25727 bool bind_to_port(
const std::string &host,
int port,
int socket_flags = 0);
25728 int bind_to_any_port(
const std::string &host,
int socket_flags = 0);
25729 bool listen_after_bind();
25731 bool listen(
const std::string &host,
int port,
int socket_flags = 0);
25733 bool is_running()
const;
25734 void wait_until_ready()
const;
25737 std::function<
TaskQueue *(void)> new_task_queue;
25740 bool process_request(
Stream &strm,
bool close_connection,
25741 bool &connection_closed,
25742 const std::function<
void(
Request &)> &setup_request);
25744 std::atomic<socket_t> svr_sock_{INVALID_SOCKET};
25745 size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT;
25746 time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND;
25747 time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
25748 time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
25749 time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
25750 time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
25751 time_t idle_interval_sec_ = CPPHTTPLIB_IDLE_INTERVAL_SECOND;
25752 time_t idle_interval_usec_ = CPPHTTPLIB_IDLE_INTERVAL_USECOND;
25753 size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH;
25757 std::vector<std::pair<std::unique_ptr<detail::MatcherBase>, Handler>>;
25758 using HandlersForContentReader =
25759 std::vector<std::pair<std::unique_ptr<detail::MatcherBase>,
25760 HandlerWithContentReader>>;
25762 static std::unique_ptr<detail::MatcherBase>
25763 make_matcher(
const std::string &pattern);
25765 Server &set_error_handler_core(HandlerWithResponse handler, std::true_type);
25766 Server &set_error_handler_core(Handler handler, std::false_type);
25768 socket_t create_server_socket(
const std::string &host,
int port,
25770 SocketOptions socket_options)
const;
25771 int bind_internal(
const std::string &host,
int port,
int socket_flags);
25772 bool listen_internal();
25776 bool head =
false);
25778 const Handlers &handlers)
const;
25779 bool dispatch_request_for_content_reader(
25781 const HandlersForContentReader &handlers)
const;
25783 bool parse_request_line(
const char *s,
Request &req)
const;
25785 std::string &content_type, std::string &boundary)
const;
25786 bool write_response(
Stream &strm,
bool close_connection,
Request &req,
25788 bool write_response_with_content(
Stream &strm,
bool close_connection,
25790 bool write_response_core(
Stream &strm,
bool close_connection,
25792 bool need_apply_ranges);
25793 bool write_content_with_provider(
Stream &strm,
const Request &req,
25794 Response &res,
const std::string &boundary,
25795 const std::string &content_type);
25799 ContentReceiver receiver,
25800 MultipartContentHeader multipart_header,
25801 ContentReceiver multipart_receiver);
25803 ContentReceiver receiver,
25804 MultipartContentHeader multipart_header,
25805 ContentReceiver multipart_receiver)
const;
25807 virtual bool process_and_close_socket(socket_t sock);
25809 std::atomic<bool> is_running_{
false};
25810 std::atomic<bool> done_{
false};
25813 std::string mount_point;
25814 std::string base_dir;
25817 std::vector<MountPointEntry> base_dirs_;
25818 std::map<std::string, std::string> file_extension_and_mimetype_map_;
25819 std::string default_file_mimetype_ =
"application/octet-stream";
25820 Handler file_request_handler_;
25822 Handlers get_handlers_;
25823 Handlers post_handlers_;
25824 HandlersForContentReader post_handlers_for_content_reader_;
25825 Handlers put_handlers_;
25826 HandlersForContentReader put_handlers_for_content_reader_;
25827 Handlers patch_handlers_;
25828 HandlersForContentReader patch_handlers_for_content_reader_;
25829 Handlers delete_handlers_;
25830 HandlersForContentReader delete_handlers_for_content_reader_;
25831 Handlers options_handlers_;
25833 HandlerWithResponse error_handler_;
25834 ExceptionHandler exception_handler_;
25835 HandlerWithResponse pre_routing_handler_;
25836 Handler post_routing_handler_;
25837 Expect100ContinueHandler expect_100_continue_handler_;
25841 int address_family_ = AF_UNSPEC;
25842 bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
25843 SocketOptions socket_options_ = default_socket_options;
25845 Headers default_headers_;
25846 std::function<ssize_t(
Stream &, Headers &)> header_writer_ =
25847 detail::write_headers;
25857 ExceedRedirectCount,
25861 SSLServerVerification,
25862 UnsupportedMultipartBoundaryChars,
25868 SSLPeerCouldBeClosed_,
25871std::string to_string(Error error);
25873std::ostream &operator<<(std::ostream &os,
const Error &obj);
25878 Result(std::unique_ptr<Response> &&res, Error err,
25879 Headers &&request_headers = Headers{})
25880 : res_(std::move(res)), err_(err),
25881 request_headers_(std::move(request_headers)) {}
25883 operator bool()
const {
return res_ !=
nullptr; }
25884 bool operator==(std::nullptr_t)
const {
return res_ ==
nullptr; }
25885 bool operator!=(std::nullptr_t)
const {
return res_ !=
nullptr; }
25886 const Response &value()
const {
return *res_; }
25887 Response &value() {
return *res_; }
25888 const Response &operator*()
const {
return *res_; }
25889 Response &operator*() {
return *res_; }
25890 const Response *operator->()
const {
return res_.get(); }
25891 Response *operator->() {
return res_.get(); }
25894 Error error()
const {
return err_; }
25897 bool has_request_header(
const std::string &key)
const;
25898 std::string get_request_header_value(
const std::string &key,
25899 size_t id = 0)
const;
25900 uint64_t get_request_header_value_u64(
const std::string &key,
25901 size_t id = 0)
const;
25902 size_t get_request_header_value_count(
const std::string &key)
const;
25905 std::unique_ptr<Response> res_;
25906 Error err_ = Error::Unknown;
25907 Headers request_headers_;
25912 explicit ClientImpl(
const std::string &host);
25914 explicit ClientImpl(
const std::string &host,
int port);
25916 explicit ClientImpl(
const std::string &host,
int port,
25917 const std::string &client_cert_path,
25918 const std::string &client_key_path);
25922 virtual bool is_valid()
const;
25924 Result Get(
const std::string &path);
25925 Result Get(
const std::string &path,
const Headers &headers);
25926 Result Get(
const std::string &path, Progress progress);
25927 Result Get(
const std::string &path,
const Headers &headers,
25928 Progress progress);
25929 Result Get(
const std::string &path, ContentReceiver content_receiver);
25930 Result Get(
const std::string &path,
const Headers &headers,
25931 ContentReceiver content_receiver);
25932 Result Get(
const std::string &path, ContentReceiver content_receiver,
25933 Progress progress);
25934 Result Get(
const std::string &path,
const Headers &headers,
25935 ContentReceiver content_receiver, Progress progress);
25936 Result Get(
const std::string &path, ResponseHandler response_handler,
25937 ContentReceiver content_receiver);
25938 Result Get(
const std::string &path,
const Headers &headers,
25939 ResponseHandler response_handler,
25940 ContentReceiver content_receiver);
25941 Result Get(
const std::string &path, ResponseHandler response_handler,
25942 ContentReceiver content_receiver, Progress progress);
25943 Result Get(
const std::string &path,
const Headers &headers,
25944 ResponseHandler response_handler, ContentReceiver content_receiver,
25945 Progress progress);
25947 Result Get(
const std::string &path,
const Params ¶ms,
25948 const Headers &headers, Progress progress =
nullptr);
25949 Result Get(
const std::string &path,
const Params ¶ms,
25950 const Headers &headers, ContentReceiver content_receiver,
25951 Progress progress =
nullptr);
25952 Result Get(
const std::string &path,
const Params ¶ms,
25953 const Headers &headers, ResponseHandler response_handler,
25954 ContentReceiver content_receiver, Progress progress =
nullptr);
25956 Result Head(
const std::string &path);
25957 Result Head(
const std::string &path,
const Headers &headers);
25959 Result Post(
const std::string &path);
25960 Result Post(
const std::string &path,
const Headers &headers);
25961 Result Post(
const std::string &path,
const char *body,
size_t content_length,
25962 const std::string &content_type);
25963 Result Post(
const std::string &path,
const Headers &headers,
const char *body,
25964 size_t content_length,
const std::string &content_type);
25965 Result Post(
const std::string &path,
const Headers &headers,
const char *body,
25966 size_t content_length,
const std::string &content_type,
25967 Progress progress);
25969 Result Post(
const std::string &path,
const std::string &body,
25970 const std::string &content_type);
25972 Result Post(
const std::string &path,
const std::string &body,
25973 const std::string &content_type, ContentReceiver content_receiver);
25975 Result Post(
const std::string &path,
const Headers &headers,
25976 const std::string &body,
25977 const std::string &content_type,
25978 ContentReceiver content_receiver);
25980 Result Post(
const std::string &path,
const std::string &body,
25981 const std::string &content_type, Progress progress);
25982 Result Post(
const std::string &path,
const Headers &headers,
25983 const std::string &body,
const std::string &content_type);
25984 Result Post(
const std::string &path,
const Headers &headers,
25985 const std::string &body,
const std::string &content_type,
25986 Progress progress);
25987 Result Post(
const std::string &path,
size_t content_length,
25988 ContentProvider content_provider,
25989 const std::string &content_type);
25990 Result Post(
const std::string &path,
25991 ContentProviderWithoutLength content_provider,
25992 const std::string &content_type);
25993 Result Post(
const std::string &path,
const Headers &headers,
25994 size_t content_length, ContentProvider content_provider,
25995 const std::string &content_type);
25996 Result Post(
const std::string &path,
const Headers &headers,
25997 ContentProviderWithoutLength content_provider,
25998 const std::string &content_type);
25999 Result Post(
const std::string &path,
const Params ¶ms);
26000 Result Post(
const std::string &path,
const Headers &headers,
26001 const Params ¶ms);
26002 Result Post(
const std::string &path,
const Headers &headers,
26003 const Params ¶ms, Progress progress);
26004 Result Post(
const std::string &path,
const MultipartFormDataItems &items);
26005 Result Post(
const std::string &path,
const Headers &headers,
26006 const MultipartFormDataItems &items);
26007 Result Post(
const std::string &path,
const Headers &headers,
26008 const MultipartFormDataItems &items,
const std::string &boundary);
26009 Result Post(
const std::string &path,
const Headers &headers,
26010 const MultipartFormDataItems &items,
26011 const MultipartFormDataProviderItems &provider_items);
26013 Result Put(
const std::string &path);
26014 Result Put(
const std::string &path,
const char *body,
size_t content_length,
26015 const std::string &content_type);
26016 Result Put(
const std::string &path,
const Headers &headers,
const char *body,
26017 size_t content_length,
const std::string &content_type);
26018 Result Put(
const std::string &path,
const Headers &headers,
const char *body,
26019 size_t content_length,
const std::string &content_type,
26020 Progress progress);
26021 Result Put(
const std::string &path,
const std::string &body,
26022 const std::string &content_type);
26023 Result Put(
const std::string &path,
const std::string &body,
26024 const std::string &content_type, Progress progress);
26025 Result Put(
const std::string &path,
const Headers &headers,
26026 const std::string &body,
const std::string &content_type);
26027 Result Put(
const std::string &path,
const Headers &headers,
26028 const std::string &body,
const std::string &content_type,
26029 Progress progress);
26030 Result Put(
const std::string &path,
size_t content_length,
26031 ContentProvider content_provider,
const std::string &content_type);
26032 Result Put(
const std::string &path,
26033 ContentProviderWithoutLength content_provider,
26034 const std::string &content_type);
26035 Result Put(
const std::string &path,
const Headers &headers,
26036 size_t content_length, ContentProvider content_provider,
26037 const std::string &content_type);
26038 Result Put(
const std::string &path,
const Headers &headers,
26039 ContentProviderWithoutLength content_provider,
26040 const std::string &content_type);
26041 Result Put(
const std::string &path,
const Params ¶ms);
26042 Result Put(
const std::string &path,
const Headers &headers,
26043 const Params ¶ms);
26044 Result Put(
const std::string &path,
const Headers &headers,
26045 const Params ¶ms, Progress progress);
26046 Result Put(
const std::string &path,
const MultipartFormDataItems &items);
26047 Result Put(
const std::string &path,
const Headers &headers,
26048 const MultipartFormDataItems &items);
26049 Result Put(
const std::string &path,
const Headers &headers,
26050 const MultipartFormDataItems &items,
const std::string &boundary);
26051 Result Put(
const std::string &path,
const Headers &headers,
26052 const MultipartFormDataItems &items,
26053 const MultipartFormDataProviderItems &provider_items);
26055 Result Patch(
const std::string &path);
26056 Result Patch(
const std::string &path,
const char *body,
size_t content_length,
26057 const std::string &content_type);
26058 Result Patch(
const std::string &path,
const char *body,
size_t content_length,
26059 const std::string &content_type, Progress progress);
26060 Result Patch(
const std::string &path,
const Headers &headers,
26061 const char *body,
size_t content_length,
26062 const std::string &content_type);
26063 Result Patch(
const std::string &path,
const Headers &headers,
26064 const char *body,
size_t content_length,
26065 const std::string &content_type, Progress progress);
26066 Result Patch(
const std::string &path,
const std::string &body,
26067 const std::string &content_type);
26068 Result Patch(
const std::string &path,
const std::string &body,
26069 const std::string &content_type, Progress progress);
26070 Result Patch(
const std::string &path,
const Headers &headers,
26071 const std::string &body,
const std::string &content_type);
26072 Result Patch(
const std::string &path,
const Headers &headers,
26073 const std::string &body,
const std::string &content_type,
26074 Progress progress);
26075 Result Patch(
const std::string &path,
size_t content_length,
26076 ContentProvider content_provider,
26077 const std::string &content_type);
26078 Result Patch(
const std::string &path,
26079 ContentProviderWithoutLength content_provider,
26080 const std::string &content_type);
26081 Result Patch(
const std::string &path,
const Headers &headers,
26082 size_t content_length, ContentProvider content_provider,
26083 const std::string &content_type);
26084 Result Patch(
const std::string &path,
const Headers &headers,
26085 ContentProviderWithoutLength content_provider,
26086 const std::string &content_type);
26088 Result Delete(
const std::string &path);
26089 Result Delete(
const std::string &path,
const Headers &headers);
26090 Result Delete(
const std::string &path,
const char *body,
26091 size_t content_length,
const std::string &content_type);
26092 Result Delete(
const std::string &path,
const char *body,
26093 size_t content_length,
const std::string &content_type,
26094 Progress progress);
26095 Result Delete(
const std::string &path,
const Headers &headers,
26096 const char *body,
size_t content_length,
26097 const std::string &content_type);
26098 Result Delete(
const std::string &path,
const Headers &headers,
26099 const char *body,
size_t content_length,
26100 const std::string &content_type, Progress progress);
26101 Result Delete(
const std::string &path,
const std::string &body,
26102 const std::string &content_type);
26103 Result Delete(
const std::string &path,
const std::string &body,
26104 const std::string &content_type, Progress progress);
26105 Result Delete(
const std::string &path,
const Headers &headers,
26106 const std::string &body,
const std::string &content_type);
26107 Result Delete(
const std::string &path,
const Headers &headers,
26108 const std::string &body,
const std::string &content_type,
26109 Progress progress);
26111 Result Options(
const std::string &path);
26112 Result Options(
const std::string &path,
const Headers &headers);
26119 std::string host()
const;
26122 size_t is_socket_open()
const;
26123 socket_t socket()
const;
26125 void set_hostname_addr_map(std::map<std::string, std::string> addr_map);
26127 void set_default_headers(Headers headers);
26130 set_header_writer(std::function<ssize_t(
Stream &, Headers &)>
const &writer);
26132 void set_address_family(
int family);
26133 void set_tcp_nodelay(
bool on);
26134 void set_socket_options(SocketOptions socket_options);
26136 void set_connection_timeout(time_t sec, time_t usec = 0);
26137 template <
class Rep,
class Period>
26139 set_connection_timeout(
const std::chrono::duration<Rep, Period> &duration);
26141 void set_read_timeout(time_t sec, time_t usec = 0);
26142 template <
class Rep,
class Period>
26143 void set_read_timeout(
const std::chrono::duration<Rep, Period> &duration);
26145 void set_write_timeout(time_t sec, time_t usec = 0);
26146 template <
class Rep,
class Period>
26147 void set_write_timeout(
const std::chrono::duration<Rep, Period> &duration);
26149 void set_basic_auth(
const std::string &username,
const std::string &password);
26150 void set_bearer_token_auth(
const std::string &token);
26151#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26152 void set_digest_auth(
const std::string &username,
26153 const std::string &password);
26156 void set_keep_alive(
bool on);
26157 void set_follow_location(
bool on);
26159 void set_url_encode(
bool on);
26161 void set_compress(
bool on);
26163 void set_decompress(
bool on);
26165 void set_interface(
const std::string &intf);
26167 void set_proxy(
const std::string &host,
int port);
26168 void set_proxy_basic_auth(
const std::string &username,
26169 const std::string &password);
26170 void set_proxy_bearer_token_auth(
const std::string &token);
26171#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26172 void set_proxy_digest_auth(
const std::string &username,
26173 const std::string &password);
26176#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26177 void set_ca_cert_path(
const std::string &ca_cert_file_path,
26178 const std::string &ca_cert_dir_path = std::string());
26179 void set_ca_cert_store(X509_STORE *ca_cert_store);
26180 X509_STORE *create_ca_cert_store(
const char *ca_cert, std::size_t size)
const;
26183#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26184 void enable_server_certificate_verification(
bool enabled);
26187 void set_logger(Logger logger);
26191 socket_t sock = INVALID_SOCKET;
26192#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26193 SSL *ssl =
nullptr;
26196 bool is_open()
const {
return sock != INVALID_SOCKET; }
26199 virtual bool create_and_connect_socket(
Socket &socket, Error &error);
26208 virtual void shutdown_ssl(
Socket &socket,
bool shutdown_gracefully);
26209 void shutdown_socket(
Socket &socket)
const;
26210 void close_socket(
Socket &socket);
26213 bool close_connection, Error &error);
26215 bool write_content_with_provider(
Stream &strm,
const Request &req,
26216 Error &error)
const;
26221 const std::string host_;
26223 const std::string host_and_port_;
26227 mutable std::mutex socket_mutex_;
26228 std::recursive_mutex request_mutex_;
26231 size_t socket_requests_in_flight_ = 0;
26232 std::thread::id socket_requests_are_from_thread_ = std::thread::id();
26233 bool socket_should_be_closed_when_request_is_done_ =
false;
26236 std::map<std::string, std::string> addr_map_;
26239 Headers default_headers_;
26242 std::function<ssize_t(
Stream &, Headers &)> header_writer_ =
26243 detail::write_headers;
26246 std::string client_cert_path_;
26247 std::string client_key_path_;
26249 time_t connection_timeout_sec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_SECOND;
26250 time_t connection_timeout_usec_ = CPPHTTPLIB_CONNECTION_TIMEOUT_USECOND;
26251 time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND;
26252 time_t read_timeout_usec_ = CPPHTTPLIB_READ_TIMEOUT_USECOND;
26253 time_t write_timeout_sec_ = CPPHTTPLIB_WRITE_TIMEOUT_SECOND;
26254 time_t write_timeout_usec_ = CPPHTTPLIB_WRITE_TIMEOUT_USECOND;
26256 std::string basic_auth_username_;
26257 std::string basic_auth_password_;
26258 std::string bearer_token_auth_token_;
26259#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26260 std::string digest_auth_username_;
26261 std::string digest_auth_password_;
26264 bool keep_alive_ =
false;
26265 bool follow_location_ =
false;
26267 bool url_encode_ =
true;
26269 int address_family_ = AF_UNSPEC;
26270 bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY;
26271 SocketOptions socket_options_ =
nullptr;
26273 bool compress_ =
false;
26274 bool decompress_ =
true;
26276 std::string interface_;
26278 std::string proxy_host_;
26279 int proxy_port_ = -1;
26281 std::string proxy_basic_auth_username_;
26282 std::string proxy_basic_auth_password_;
26283 std::string proxy_bearer_token_auth_token_;
26284#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26285 std::string proxy_digest_auth_username_;
26286 std::string proxy_digest_auth_password_;
26289#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26290 std::string ca_cert_file_path_;
26291 std::string ca_cert_dir_path_;
26293 X509_STORE *ca_cert_store_ =
nullptr;
26296#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26297 bool server_certificate_verification_ =
true;
26306 socket_t create_client_socket(Error &error)
const;
26309 bool write_request(
Stream &strm,
Request &req,
bool close_connection,
26313 bool close_connection, Error &error);
26314 std::unique_ptr<Response> send_with_content_provider(
26315 Request &req,
const char *body,
size_t content_length,
26316 ContentProvider content_provider,
26317 ContentProviderWithoutLength content_provider_without_length,
26318 const std::string &content_type, Error &error, ContentReceiver content_receiver=
nullptr);
26319 Result send_with_content_provider(
26320 const std::string &method,
const std::string &path,
26321 const Headers &headers,
const char *body,
size_t content_length,
26322 ContentProvider content_provider,
26323 ContentProviderWithoutLength content_provider_without_length,
26324 const std::string &content_type, Progress progress, ContentReceiver content_receiver=
nullptr);
26325 ContentProviderWithoutLength get_multipart_content_provider(
26326 const std::string &boundary,
const MultipartFormDataItems &items,
26327 const MultipartFormDataProviderItems &provider_items)
const;
26329 std::string adjust_host_string(
const std::string &host)
const;
26331 virtual bool process_socket(
const Socket &socket,
26332 std::function<
bool(
Stream &strm)> callback);
26333 virtual bool is_ssl()
const;
26339 explicit Client(
const std::string &scheme_host_port);
26341 explicit Client(
const std::string &scheme_host_port,
26342 const std::string &client_cert_path,
26343 const std::string &client_key_path);
26346 explicit Client(
const std::string &host,
int port);
26348 explicit Client(
const std::string &host,
int port,
26349 const std::string &client_cert_path,
26350 const std::string &client_key_path);
26356 bool is_valid()
const;
26358 Result Get(
const std::string &path);
26359 Result Get(
const std::string &path,
const Headers &headers);
26360 Result Get(
const std::string &path, Progress progress);
26361 Result Get(
const std::string &path,
const Headers &headers,
26362 Progress progress);
26363 Result Get(
const std::string &path, ContentReceiver content_receiver);
26364 Result Get(
const std::string &path,
const Headers &headers,
26365 ContentReceiver content_receiver);
26366 Result Get(
const std::string &path, ContentReceiver content_receiver,
26367 Progress progress);
26368 Result Get(
const std::string &path,
const Headers &headers,
26369 ContentReceiver content_receiver, Progress progress);
26370 Result Get(
const std::string &path, ResponseHandler response_handler,
26371 ContentReceiver content_receiver);
26372 Result Get(
const std::string &path,
const Headers &headers,
26373 ResponseHandler response_handler,
26374 ContentReceiver content_receiver);
26375 Result Get(
const std::string &path,
const Headers &headers,
26376 ResponseHandler response_handler, ContentReceiver content_receiver,
26377 Progress progress);
26378 Result Get(
const std::string &path, ResponseHandler response_handler,
26379 ContentReceiver content_receiver, Progress progress);
26381 Result Get(
const std::string &path,
const Params ¶ms,
26382 const Headers &headers, Progress progress =
nullptr);
26383 Result Get(
const std::string &path,
const Params ¶ms,
26384 const Headers &headers, ContentReceiver content_receiver,
26385 Progress progress =
nullptr);
26386 Result Get(
const std::string &path,
const Params ¶ms,
26387 const Headers &headers, ResponseHandler response_handler,
26388 ContentReceiver content_receiver, Progress progress =
nullptr);
26390 Result Head(
const std::string &path);
26391 Result Head(
const std::string &path,
const Headers &headers);
26393 Result Post(
const std::string &path);
26394 Result Post(
const std::string &path,
const Headers &headers);
26395 Result Post(
const std::string &path,
const char *body,
size_t content_length,
26396 const std::string &content_type);
26397 Result Post(
const std::string &path,
const Headers &headers,
const char *body,
26398 size_t content_length,
const std::string &content_type);
26399 Result Post(
const std::string &path,
const Headers &headers,
const char *body,
26400 size_t content_length,
const std::string &content_type,
26401 Progress progress);
26402 Result Post(
const std::string &path,
const std::string &body,
26403 const std::string &content_type);
26404 Result Post(
const std::string &path,
const std::string &body,
26405 const std::string &content_type, ContentReceiver content_receiver);
26406 Result Post(
const std::string &path,
const std::string &body,
26407 const std::string &content_type, Progress progress);
26408 Result Post(
const std::string &path,
const Headers &headers,
26409 const std::string &body,
const std::string &content_type);
26410 Result Post(
const std::string &path,
const Headers &headers,
26411 const std::string &body,
const std::string &content_type,
26412 Progress progress);
26413 Result Post(
const std::string &path,
const Headers &headers,
26414 const std::string &body,
26415 const std::string &content_type,
26416 ContentReceiver content_receiver);
26417 Result Post(
const std::string &path,
size_t content_length,
26418 ContentProvider content_provider,
26419 const std::string &content_type);
26420 Result Post(
const std::string &path,
26421 ContentProviderWithoutLength content_provider,
26422 const std::string &content_type);
26423 Result Post(
const std::string &path,
const Headers &headers,
26424 size_t content_length, ContentProvider content_provider,
26425 const std::string &content_type);
26426 Result Post(
const std::string &path,
const Headers &headers,
26427 ContentProviderWithoutLength content_provider,
26428 const std::string &content_type);
26429 Result Post(
const std::string &path,
const Params ¶ms);
26430 Result Post(
const std::string &path,
const Headers &headers,
26431 const Params ¶ms);
26432 Result Post(
const std::string &path,
const Headers &headers,
26433 const Params ¶ms, Progress progress);
26434 Result Post(
const std::string &path,
const MultipartFormDataItems &items);
26435 Result Post(
const std::string &path,
const Headers &headers,
26436 const MultipartFormDataItems &items);
26437 Result Post(
const std::string &path,
const Headers &headers,
26438 const MultipartFormDataItems &items,
const std::string &boundary);
26439 Result Post(
const std::string &path,
const Headers &headers,
26440 const MultipartFormDataItems &items,
26441 const MultipartFormDataProviderItems &provider_items);
26443 Result Put(
const std::string &path);
26444 Result Put(
const std::string &path,
const char *body,
size_t content_length,
26445 const std::string &content_type);
26446 Result Put(
const std::string &path,
const Headers &headers,
const char *body,
26447 size_t content_length,
const std::string &content_type);
26448 Result Put(
const std::string &path,
const Headers &headers,
const char *body,
26449 size_t content_length,
const std::string &content_type,
26450 Progress progress);
26451 Result Put(
const std::string &path,
const std::string &body,
26452 const std::string &content_type);
26453 Result Put(
const std::string &path,
const std::string &body,
26454 const std::string &content_type, Progress progress);
26455 Result Put(
const std::string &path,
const Headers &headers,
26456 const std::string &body,
const std::string &content_type);
26457 Result Put(
const std::string &path,
const Headers &headers,
26458 const std::string &body,
const std::string &content_type,
26459 Progress progress);
26460 Result Put(
const std::string &path,
size_t content_length,
26461 ContentProvider content_provider,
const std::string &content_type);
26462 Result Put(
const std::string &path,
26463 ContentProviderWithoutLength content_provider,
26464 const std::string &content_type);
26465 Result Put(
const std::string &path,
const Headers &headers,
26466 size_t content_length, ContentProvider content_provider,
26467 const std::string &content_type);
26468 Result Put(
const std::string &path,
const Headers &headers,
26469 ContentProviderWithoutLength content_provider,
26470 const std::string &content_type);
26471 Result Put(
const std::string &path,
const Params ¶ms);
26472 Result Put(
const std::string &path,
const Headers &headers,
26473 const Params ¶ms);
26474 Result Put(
const std::string &path,
const Headers &headers,
26475 const Params ¶ms, Progress progress);
26476 Result Put(
const std::string &path,
const MultipartFormDataItems &items);
26477 Result Put(
const std::string &path,
const Headers &headers,
26478 const MultipartFormDataItems &items);
26479 Result Put(
const std::string &path,
const Headers &headers,
26480 const MultipartFormDataItems &items,
const std::string &boundary);
26481 Result Put(
const std::string &path,
const Headers &headers,
26482 const MultipartFormDataItems &items,
26483 const MultipartFormDataProviderItems &provider_items);
26485 Result Patch(
const std::string &path);
26486 Result Patch(
const std::string &path,
const char *body,
size_t content_length,
26487 const std::string &content_type);
26488 Result Patch(
const std::string &path,
const char *body,
size_t content_length,
26489 const std::string &content_type, Progress progress);
26490 Result Patch(
const std::string &path,
const Headers &headers,
26491 const char *body,
size_t content_length,
26492 const std::string &content_type);
26493 Result Patch(
const std::string &path,
const Headers &headers,
26494 const char *body,
size_t content_length,
26495 const std::string &content_type, Progress progress);
26496 Result Patch(
const std::string &path,
const std::string &body,
26497 const std::string &content_type);
26498 Result Patch(
const std::string &path,
const std::string &body,
26499 const std::string &content_type, Progress progress);
26500 Result Patch(
const std::string &path,
const Headers &headers,
26501 const std::string &body,
const std::string &content_type);
26502 Result Patch(
const std::string &path,
const Headers &headers,
26503 const std::string &body,
const std::string &content_type,
26504 Progress progress);
26505 Result Patch(
const std::string &path,
size_t content_length,
26506 ContentProvider content_provider,
26507 const std::string &content_type);
26508 Result Patch(
const std::string &path,
26509 ContentProviderWithoutLength content_provider,
26510 const std::string &content_type);
26511 Result Patch(
const std::string &path,
const Headers &headers,
26512 size_t content_length, ContentProvider content_provider,
26513 const std::string &content_type);
26514 Result Patch(
const std::string &path,
const Headers &headers,
26515 ContentProviderWithoutLength content_provider,
26516 const std::string &content_type);
26518 Result Delete(
const std::string &path);
26519 Result Delete(
const std::string &path,
const Headers &headers);
26520 Result Delete(
const std::string &path,
const char *body,
26521 size_t content_length,
const std::string &content_type);
26522 Result Delete(
const std::string &path,
const char *body,
26523 size_t content_length,
const std::string &content_type,
26524 Progress progress);
26525 Result Delete(
const std::string &path,
const Headers &headers,
26526 const char *body,
size_t content_length,
26527 const std::string &content_type);
26528 Result Delete(
const std::string &path,
const Headers &headers,
26529 const char *body,
size_t content_length,
26530 const std::string &content_type, Progress progress);
26531 Result Delete(
const std::string &path,
const std::string &body,
26532 const std::string &content_type);
26533 Result Delete(
const std::string &path,
const std::string &body,
26534 const std::string &content_type, Progress progress);
26535 Result Delete(
const std::string &path,
const Headers &headers,
26536 const std::string &body,
const std::string &content_type);
26537 Result Delete(
const std::string &path,
const Headers &headers,
26538 const std::string &body,
const std::string &content_type,
26539 Progress progress);
26541 Result Options(
const std::string &path);
26542 Result Options(
const std::string &path,
const Headers &headers);
26549 std::string host()
const;
26552 size_t is_socket_open()
const;
26553 socket_t socket()
const;
26555 void set_hostname_addr_map(std::map<std::string, std::string> addr_map);
26557 void set_default_headers(Headers headers);
26560 set_header_writer(std::function<ssize_t(
Stream &, Headers &)>
const &writer);
26562 void set_address_family(
int family);
26563 void set_tcp_nodelay(
bool on);
26564 void set_socket_options(SocketOptions socket_options);
26566 void set_connection_timeout(time_t sec, time_t usec = 0);
26567 template <
class Rep,
class Period>
26569 set_connection_timeout(
const std::chrono::duration<Rep, Period> &duration);
26571 void set_read_timeout(time_t sec, time_t usec = 0);
26572 template <
class Rep,
class Period>
26573 void set_read_timeout(
const std::chrono::duration<Rep, Period> &duration);
26575 void set_write_timeout(time_t sec, time_t usec = 0);
26576 template <
class Rep,
class Period>
26577 void set_write_timeout(
const std::chrono::duration<Rep, Period> &duration);
26579 void set_basic_auth(
const std::string &username,
const std::string &password);
26580 void set_bearer_token_auth(
const std::string &token);
26581#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26582 void set_digest_auth(
const std::string &username,
26583 const std::string &password);
26586 void set_keep_alive(
bool on);
26587 void set_follow_location(
bool on);
26589 void set_url_encode(
bool on);
26591 void set_compress(
bool on);
26593 void set_decompress(
bool on);
26595 void set_interface(
const std::string &intf);
26597 void set_proxy(
const std::string &host,
int port);
26598 void set_proxy_basic_auth(
const std::string &username,
26599 const std::string &password);
26600 void set_proxy_bearer_token_auth(
const std::string &token);
26601#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26602 void set_proxy_digest_auth(
const std::string &username,
26603 const std::string &password);
26606#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26607 void enable_server_certificate_verification(
bool enabled);
26610 void set_logger(Logger logger);
26613#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26614 void set_ca_cert_path(
const std::string &ca_cert_file_path,
26615 const std::string &ca_cert_dir_path = std::string());
26617 void set_ca_cert_store(X509_STORE *ca_cert_store);
26618 void load_ca_cert_store(
const char *ca_cert, std::size_t size);
26620 long get_openssl_verify_result()
const;
26622 SSL_CTX *ssl_context()
const;
26626 std::unique_ptr<ClientImpl> cli_;
26628#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26629 bool is_ssl_ =
false;
26633#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
26634class SSLServer :
public Server {
26636 SSLServer(
const char *cert_path,
const char *private_key_path,
26637 const char *client_ca_cert_file_path =
nullptr,
26638 const char *client_ca_cert_dir_path =
nullptr,
26639 const char *private_key_password =
nullptr);
26641 SSLServer(X509 *cert, EVP_PKEY *private_key,
26642 X509_STORE *client_ca_cert_store =
nullptr);
26645 const std::function<
bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback);
26647 ~SSLServer()
override;
26649 bool is_valid()
const override;
26651 SSL_CTX *ssl_context()
const;
26654 bool process_and_close_socket(socket_t sock)
override;
26657 std::mutex ctx_mutex_;
26660class SSLClient final :
public ClientImpl {
26662 explicit SSLClient(
const std::string &host);
26664 explicit SSLClient(
const std::string &host,
int port);
26666 explicit SSLClient(
const std::string &host,
int port,
26667 const std::string &client_cert_path,
26668 const std::string &client_key_path,
26669 const std::string &private_key_password = std::string());
26671 explicit SSLClient(
const std::string &host,
int port, X509 *client_cert,
26672 EVP_PKEY *client_key,
26673 const std::string &private_key_password = std::string());
26675 ~SSLClient()
override;
26677 bool is_valid()
const override;
26679 void set_ca_cert_store(X509_STORE *ca_cert_store);
26680 void load_ca_cert_store(
const char *ca_cert, std::size_t size);
26682 long get_openssl_verify_result()
const;
26684 SSL_CTX *ssl_context()
const;
26687 bool create_and_connect_socket(Socket &socket, Error &error)
override;
26688 void shutdown_ssl(Socket &socket,
bool shutdown_gracefully)
override;
26689 void shutdown_ssl_impl(Socket &socket,
bool shutdown_gracefully);
26691 bool process_socket(
const Socket &socket,
26692 std::function<
bool(Stream &strm)> callback)
override;
26693 bool is_ssl()
const override;
26695 bool connect_with_proxy(Socket &sock, Response &res,
bool &success,
26697 bool initialize_ssl(Socket &socket, Error &error);
26701 bool verify_host(X509 *server_cert)
const;
26702 bool verify_host_with_subject_alt_name(X509 *server_cert)
const;
26703 bool verify_host_with_common_name(X509 *server_cert)
const;
26704 bool check_host_name(
const char *pattern,
size_t pattern_len)
const;
26707 std::mutex ctx_mutex_;
26708 std::once_flag initialize_cert_;
26710 std::vector<std::string> host_components_;
26712 long verify_result_ = 0;
26714 friend class ClientImpl;
26724template <
typename T,
typename U>
26725inline void duration_to_sec_and_usec(
const T &duration, U callback) {
26726 auto sec = std::chrono::duration_cast<std::chrono::seconds>(duration).count();
26727 auto usec = std::chrono::duration_cast<std::chrono::microseconds>(
26728 duration - std::chrono::seconds(sec))
26730 callback(
static_cast<time_t
>(sec),
static_cast<time_t
>(usec));
26733inline uint64_t get_header_value_u64(
const Headers &headers,
26734 const std::string &key,
size_t id,
26736 auto rng = headers.equal_range(key);
26737 auto it = rng.first;
26738 std::advance(it,
static_cast<ssize_t
>(
id));
26739 if (it != rng.second) {
26740 return std::strtoull(it->second.data(),
nullptr, 10);
26747inline uint64_t Request::get_header_value_u64(
const std::string &key,
26749 return detail::get_header_value_u64(headers, key,
id, 0);
26752inline uint64_t Response::get_header_value_u64(
const std::string &key,
26754 return detail::get_header_value_u64(headers, key,
id, 0);
26757template <
typename... Args>
26758inline ssize_t Stream::write_format(
const char *fmt,
const Args &...args) {
26759 const auto bufsiz = 2048;
26760 std::array<char, bufsiz> buf{};
26762 auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...);
26763 if (sn <= 0) {
return sn; }
26765 auto n =
static_cast<size_t>(sn);
26767 if (n >= buf.size() - 1) {
26768 std::vector<char> glowable_buf(buf.size());
26770 while (n >= glowable_buf.size() - 1) {
26771 glowable_buf.resize(glowable_buf.size() * 2);
26772 n =
static_cast<size_t>(
26773 snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...));
26775 return write(&glowable_buf[0], n);
26777 return write(buf.data(), n);
26781inline void default_socket_options(socket_t sock) {
26784 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
26785 reinterpret_cast<const char *
>(&yes),
sizeof(yes));
26786 setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE,
26787 reinterpret_cast<const char *
>(&yes),
sizeof(yes));
26790 setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
26791 reinterpret_cast<const void *
>(&yes),
sizeof(yes));
26793 setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
26794 reinterpret_cast<const void *
>(&yes),
sizeof(yes));
26799inline const char *status_message(
int status) {
26801 case StatusCode::Continue_100:
return "Continue";
26802 case StatusCode::SwitchingProtocol_101:
return "Switching Protocol";
26803 case StatusCode::Processing_102:
return "Processing";
26804 case StatusCode::EarlyHints_103:
return "Early Hints";
26805 case StatusCode::OK_200:
return "OK";
26806 case StatusCode::Created_201:
return "Created";
26807 case StatusCode::Accepted_202:
return "Accepted";
26808 case StatusCode::NonAuthoritativeInformation_203:
26809 return "Non-Authoritative Information";
26810 case StatusCode::NoContent_204:
return "No Content";
26811 case StatusCode::ResetContent_205:
return "Reset Content";
26812 case StatusCode::PartialContent_206:
return "Partial Content";
26813 case StatusCode::MultiStatus_207:
return "Multi-Status";
26814 case StatusCode::AlreadyReported_208:
return "Already Reported";
26815 case StatusCode::IMUsed_226:
return "IM Used";
26816 case StatusCode::MultipleChoices_300:
return "Multiple Choices";
26817 case StatusCode::MovedPermanently_301:
return "Moved Permanently";
26818 case StatusCode::Found_302:
return "Found";
26819 case StatusCode::SeeOther_303:
return "See Other";
26820 case StatusCode::NotModified_304:
return "Not Modified";
26821 case StatusCode::UseProxy_305:
return "Use Proxy";
26822 case StatusCode::unused_306:
return "unused";
26823 case StatusCode::TemporaryRedirect_307:
return "Temporary Redirect";
26824 case StatusCode::PermanentRedirect_308:
return "Permanent Redirect";
26825 case StatusCode::BadRequest_400:
return "Bad Request";
26826 case StatusCode::Unauthorized_401:
return "Unauthorized";
26827 case StatusCode::PaymentRequired_402:
return "Payment Required";
26828 case StatusCode::Forbidden_403:
return "Forbidden";
26829 case StatusCode::NotFound_404:
return "Not Found";
26830 case StatusCode::MethodNotAllowed_405:
return "Method Not Allowed";
26831 case StatusCode::NotAcceptable_406:
return "Not Acceptable";
26832 case StatusCode::ProxyAuthenticationRequired_407:
26833 return "Proxy Authentication Required";
26834 case StatusCode::RequestTimeout_408:
return "Request Timeout";
26835 case StatusCode::Conflict_409:
return "Conflict";
26836 case StatusCode::Gone_410:
return "Gone";
26837 case StatusCode::LengthRequired_411:
return "Length Required";
26838 case StatusCode::PreconditionFailed_412:
return "Precondition Failed";
26839 case StatusCode::PayloadTooLarge_413:
return "Payload Too Large";
26840 case StatusCode::UriTooLong_414:
return "URI Too Long";
26841 case StatusCode::UnsupportedMediaType_415:
return "Unsupported Media Type";
26842 case StatusCode::RangeNotSatisfiable_416:
return "Range Not Satisfiable";
26843 case StatusCode::ExpectationFailed_417:
return "Expectation Failed";
26844 case StatusCode::ImATeapot_418:
return "I'm a teapot";
26845 case StatusCode::MisdirectedRequest_421:
return "Misdirected Request";
26846 case StatusCode::UnprocessableContent_422:
return "Unprocessable Content";
26847 case StatusCode::Locked_423:
return "Locked";
26848 case StatusCode::FailedDependency_424:
return "Failed Dependency";
26849 case StatusCode::TooEarly_425:
return "Too Early";
26850 case StatusCode::UpgradeRequired_426:
return "Upgrade Required";
26851 case StatusCode::PreconditionRequired_428:
return "Precondition Required";
26852 case StatusCode::TooManyRequests_429:
return "Too Many Requests";
26853 case StatusCode::RequestHeaderFieldsTooLarge_431:
26854 return "Request Header Fields Too Large";
26855 case StatusCode::UnavailableForLegalReasons_451:
26856 return "Unavailable For Legal Reasons";
26857 case StatusCode::NotImplemented_501:
return "Not Implemented";
26858 case StatusCode::BadGateway_502:
return "Bad Gateway";
26859 case StatusCode::ServiceUnavailable_503:
return "Service Unavailable";
26860 case StatusCode::GatewayTimeout_504:
return "Gateway Timeout";
26861 case StatusCode::HttpVersionNotSupported_505:
26862 return "HTTP Version Not Supported";
26863 case StatusCode::VariantAlsoNegotiates_506:
return "Variant Also Negotiates";
26864 case StatusCode::InsufficientStorage_507:
return "Insufficient Storage";
26865 case StatusCode::LoopDetected_508:
return "Loop Detected";
26866 case StatusCode::NotExtended_510:
return "Not Extended";
26867 case StatusCode::NetworkAuthenticationRequired_511:
26868 return "Network Authentication Required";
26871 case StatusCode::InternalServerError_500:
return "Internal Server Error";
26875inline std::string get_bearer_token_auth(
const Request &req) {
26876 if (req.has_header(
"Authorization")) {
26877 static std::string BearerHeaderPrefix =
"Bearer ";
26878 return req.get_header_value(
"Authorization")
26879 .substr(BearerHeaderPrefix.length());
26884template <
class Rep,
class Period>
26886Server::set_read_timeout(
const std::chrono::duration<Rep, Period> &duration) {
26887 detail::duration_to_sec_and_usec(
26888 duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); });
26892template <
class Rep,
class Period>
26894Server::set_write_timeout(
const std::chrono::duration<Rep, Period> &duration) {
26895 detail::duration_to_sec_and_usec(
26896 duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); });
26900template <
class Rep,
class Period>
26902Server::set_idle_interval(
const std::chrono::duration<Rep, Period> &duration) {
26903 detail::duration_to_sec_and_usec(
26904 duration, [&](time_t sec, time_t usec) { set_idle_interval(sec, usec); });
26908inline std::string to_string(
const Error error) {
26910 case Error::Success:
return "Success (no error)";
26911 case Error::Connection:
return "Could not establish connection";
26912 case Error::BindIPAddress:
return "Failed to bind IP address";
26913 case Error::Read:
return "Failed to read connection";
26914 case Error::Write:
return "Failed to write connection";
26915 case Error::ExceedRedirectCount:
return "Maximum redirect count exceeded";
26916 case Error::Canceled:
return "Connection handling canceled";
26917 case Error::SSLConnection:
return "SSL connection failed";
26918 case Error::SSLLoadingCerts:
return "SSL certificate loading failed";
26919 case Error::SSLServerVerification:
return "SSL server verification failed";
26920 case Error::UnsupportedMultipartBoundaryChars:
26921 return "Unsupported HTTP multipart boundary characters";
26922 case Error::Compression:
return "Compression failed";
26923 case Error::ConnectionTimeout:
return "Connection timed out";
26924 case Error::ProxyConnection:
return "Proxy connection failed";
26925 case Error::Unknown:
return "Unknown";
26932inline std::ostream &operator<<(std::ostream &os,
const Error &obj) {
26933 os << to_string(obj);
26934 os <<
" (" <<
static_cast<std::underlying_type<Error>::type
>(obj) <<
')';
26938inline uint64_t Result::get_request_header_value_u64(
const std::string &key,
26940 return detail::get_header_value_u64(request_headers_, key,
id, 0);
26943template <
class Rep,
class Period>
26944inline void ClientImpl::set_connection_timeout(
26945 const std::chrono::duration<Rep, Period> &duration) {
26946 detail::duration_to_sec_and_usec(duration, [&](time_t sec, time_t usec) {
26947 set_connection_timeout(sec, usec);
26951template <
class Rep,
class Period>
26952inline void ClientImpl::set_read_timeout(
26953 const std::chrono::duration<Rep, Period> &duration) {
26954 detail::duration_to_sec_and_usec(
26955 duration, [&](time_t sec, time_t usec) { set_read_timeout(sec, usec); });
26958template <
class Rep,
class Period>
26959inline void ClientImpl::set_write_timeout(
26960 const std::chrono::duration<Rep, Period> &duration) {
26961 detail::duration_to_sec_and_usec(
26962 duration, [&](time_t sec, time_t usec) { set_write_timeout(sec, usec); });
26965template <
class Rep,
class Period>
26966inline void Client::set_connection_timeout(
26967 const std::chrono::duration<Rep, Period> &duration) {
26968 cli_->set_connection_timeout(duration);
26971template <
class Rep,
class Period>
26973Client::set_read_timeout(
const std::chrono::duration<Rep, Period> &duration) {
26974 cli_->set_read_timeout(duration);
26977template <
class Rep,
class Period>
26979Client::set_write_timeout(
const std::chrono::duration<Rep, Period> &duration) {
26980 cli_->set_write_timeout(duration);
26988std::string hosted_at(
const std::string &hostname);
26990void hosted_at(
const std::string &hostname, std::vector<std::string> &addrs);
26992std::string append_query_params(
const std::string &path,
const Params ¶ms);
26994std::pair<std::string, std::string> make_range_header(
const Ranges &ranges);
26996std::pair<std::string, std::string>
26997make_basic_authentication_header(
const std::string &username,
26998 const std::string &password,
26999 bool is_proxy =
false);
27003std::string encode_query_param(
const std::string &value);
27005std::string decode_url(
const std::string &s,
bool convert_plus_to_space);
27007void read_file(
const std::string &path, std::string &out);
27009std::string trim_copy(
const std::string &s);
27012 const char *data, std::size_t size,
char d,
27013 std::function<
void(
const char *, std::size_t,
const char *, std::size_t)>
27017 const std::string &str,
char d,
27018 std::function<
void(
const char *, std::size_t,
const char *, std::size_t)>
27021void split(
const char *b,
const char *e,
char d,
27022 std::function<
void(
const char *,
const char *)> fn);
27024void split(
const char *b,
const char *e,
char d,
size_t m,
27025 std::function<
void(
const char *,
const char *)> fn);
27027bool process_client_socket(socket_t sock, time_t read_timeout_sec,
27028 time_t read_timeout_usec, time_t write_timeout_sec,
27029 time_t write_timeout_usec,
27030 std::function<
bool(Stream &)> callback);
27032socket_t create_client_socket(
27033 const std::string &host,
const std::string &ip,
int port,
27034 int address_family,
bool tcp_nodelay, SocketOptions socket_options,
27035 time_t connection_timeout_sec, time_t connection_timeout_usec,
27036 time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
27037 time_t write_timeout_usec,
const std::string &intf, Error &error);
27039const char *get_header_value(
const Headers &headers,
const std::string &key,
27040 size_t id = 0,
const char *def =
nullptr);
27042std::string params_to_query_str(
const Params ¶ms);
27044void parse_query_text(
const char *data, std::size_t size, Params ¶ms);
27046void parse_query_text(
const std::string &s, Params ¶ms);
27048bool parse_multipart_boundary(
const std::string &content_type,
27049 std::string &boundary);
27051bool parse_range_header(
const std::string &s, Ranges &ranges);
27053int close_socket(socket_t sock);
27055ssize_t send_socket(socket_t sock,
const void *ptr,
size_t size,
int flags);
27057ssize_t read_socket(socket_t sock,
void *ptr,
size_t size,
int flags);
27059enum class EncodingType { None = 0, Gzip, Brotli };
27061EncodingType encoding_type(
const Request &req,
const Response &res);
27068 bool is_readable()
const override;
27069 bool is_writable()
const override;
27070 ssize_t read(
char *ptr,
size_t size)
override;
27071 ssize_t write(
const char *ptr,
size_t size)
override;
27072 void get_remote_ip_and_port(std::string &ip,
int &port)
const override;
27073 void get_local_ip_and_port(std::string &ip,
int &port)
const override;
27074 socket_t socket()
const override;
27076 const std::string &get_buffer()
const;
27079 std::string buffer;
27080 size_t position = 0;
27087 typedef std::function<bool(
const char *data,
size_t data_len)> Callback;
27088 virtual bool compress(
const char *data,
size_t data_length,
bool last,
27089 Callback callback) = 0;
27096 virtual bool is_valid()
const = 0;
27098 typedef std::function<bool(
const char *data,
size_t data_len)> Callback;
27099 virtual bool decompress(
const char *data,
size_t data_length,
27100 Callback callback) = 0;
27107 bool compress(
const char *data,
size_t data_length,
bool ,
27108 Callback callback)
override;
27111#ifdef CPPHTTPLIB_ZLIB_SUPPORT
27112class gzip_compressor final :
public compressor {
27115 ~gzip_compressor()
override;
27117 bool compress(
const char *data,
size_t data_length,
bool last,
27118 Callback callback)
override;
27121 bool is_valid_ =
false;
27125class gzip_decompressor final :
public decompressor {
27127 gzip_decompressor();
27128 ~gzip_decompressor()
override;
27130 bool is_valid()
const override;
27132 bool decompress(
const char *data,
size_t data_length,
27133 Callback callback)
override;
27136 bool is_valid_ =
false;
27141#ifdef CPPHTTPLIB_BROTLI_SUPPORT
27142class brotli_compressor final :
public compressor {
27144 brotli_compressor();
27145 ~brotli_compressor();
27147 bool compress(
const char *data,
size_t data_length,
bool last,
27148 Callback callback)
override;
27151 BrotliEncoderState *state_ =
nullptr;
27154class brotli_decompressor final :
public decompressor {
27156 brotli_decompressor();
27157 ~brotli_decompressor();
27159 bool is_valid()
const override;
27161 bool decompress(
const char *data,
size_t data_length,
27162 Callback callback)
override;
27165 BrotliDecoderResult decoder_r;
27166 BrotliDecoderState *decoder_s =
nullptr;
27175 size_t fixed_buffer_size);
27176 const char *ptr()
const;
27177 size_t size()
const;
27178 bool end_with_crlf()
const;
27182 void append(
char c);
27185 char *fixed_buffer_;
27186 const size_t fixed_buffer_size_;
27187 size_t fixed_buffer_used_size_ = 0;
27188 std::string glowable_buffer_;
27193 mmap(
const char *path);
27196 bool open(
const char *path);
27199 bool is_open()
const;
27200 size_t size()
const;
27201 const char *data()
const;
27224inline bool is_hex(
char c,
int &v) {
27225 if (0x20 <= c && isdigit(c)) {
27228 }
else if (
'A' <= c && c <=
'F') {
27231 }
else if (
'a' <= c && c <=
'f') {
27238inline bool from_hex_to_i(
const std::string &s,
size_t i,
size_t cnt,
27240 if (i >= s.size()) {
return false; }
27243 for (; cnt; i++, cnt--) {
27244 if (!s[i]) {
return false; }
27246 if (is_hex(s[i], v)) {
27247 val = val * 16 + v;
27255inline std::string from_i_to_hex(
size_t n) {
27256 static const auto charset =
"0123456789abcdef";
27259 ret = charset[n & 15] + ret;
27265inline size_t to_utf8(
int code,
char *buff) {
27266 if (code < 0x0080) {
27267 buff[0] =
static_cast<char>(code & 0x7F);
27269 }
else if (code < 0x0800) {
27270 buff[0] =
static_cast<char>(0xC0 | ((code >> 6) & 0x1F));
27271 buff[1] =
static_cast<char>(0x80 | (code & 0x3F));
27273 }
else if (code < 0xD800) {
27274 buff[0] =
static_cast<char>(0xE0 | ((code >> 12) & 0xF));
27275 buff[1] =
static_cast<char>(0x80 | ((code >> 6) & 0x3F));
27276 buff[2] =
static_cast<char>(0x80 | (code & 0x3F));
27278 }
else if (code < 0xE000) {
27280 }
else if (code < 0x10000) {
27281 buff[0] =
static_cast<char>(0xE0 | ((code >> 12) & 0xF));
27282 buff[1] =
static_cast<char>(0x80 | ((code >> 6) & 0x3F));
27283 buff[2] =
static_cast<char>(0x80 | (code & 0x3F));
27285 }
else if (code < 0x110000) {
27286 buff[0] =
static_cast<char>(0xF0 | ((code >> 18) & 0x7));
27287 buff[1] =
static_cast<char>(0x80 | ((code >> 12) & 0x3F));
27288 buff[2] =
static_cast<char>(0x80 | ((code >> 6) & 0x3F));
27289 buff[3] =
static_cast<char>(0x80 | (code & 0x3F));
27299inline std::string base64_encode(
const std::string &in) {
27300 static const auto lookup =
27301 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
27304 out.reserve(in.size());
27309 for (
auto c : in) {
27310 val = (val << 8) + static_cast<uint8_t>(c);
27312 while (valb >= 0) {
27313 out.push_back(lookup[(val >> valb) & 0x3F]);
27318 if (valb > -6) { out.push_back(lookup[((val << 8) >> (valb + 8)) & 0x3F]); }
27320 while (out.size() % 4) {
27321 out.push_back(
'=');
27327inline bool is_file(
const std::string &path) {
27329 return _access_s(path.c_str(), 0) == 0;
27332 return stat(path.c_str(), &st) >= 0 && S_ISREG(st.st_mode);
27336inline bool is_dir(
const std::string &path) {
27338 return stat(path.c_str(), &st) >= 0 && S_ISDIR(st.st_mode);
27341inline bool is_valid_path(
const std::string &path) {
27346 while (i < path.size() && path[i] ==
'/') {
27350 while (i < path.size()) {
27353 while (i < path.size() && path[i] !=
'/') {
27354 if (path[i] ==
'\0') {
27356 }
else if (path[i] ==
'\\') {
27362 auto len = i - beg;
27365 if (!path.compare(beg, len,
".")) {
27367 }
else if (!path.compare(beg, len,
"..")) {
27368 if (level == 0) {
return false; }
27375 while (i < path.size() && path[i] ==
'/') {
27383inline std::string encode_query_param(
const std::string &value) {
27384 std::ostringstream escaped;
27386 escaped << std::hex;
27388 for (
auto c :
value) {
27389 if (std::isalnum(
static_cast<uint8_t
>(c)) || c ==
'-' || c ==
'_' ||
27390 c ==
'.' || c ==
'!' || c ==
'~' || c ==
'*' || c ==
'\'' || c ==
'(' ||
27394 escaped << std::uppercase;
27395 escaped <<
'%' << std::setw(2)
27396 <<
static_cast<int>(
static_cast<unsigned char>(c));
27397 escaped << std::nouppercase;
27401 return escaped.str();
27404inline std::string encode_url(
const std::string &s) {
27405 std::string result;
27406 result.reserve(s.size());
27408 for (
size_t i = 0; s[i]; i++) {
27410 case ' ': result +=
"%20";
break;
27411 case '+': result +=
"%2B";
break;
27412 case '\r': result +=
"%0D";
break;
27413 case '\n': result +=
"%0A";
break;
27414 case '\'': result +=
"%27";
break;
27415 case ',': result +=
"%2C";
break;
27417 case ';': result +=
"%3B";
break;
27419 auto c =
static_cast<uint8_t
>(s[i]);
27423 auto len = snprintf(hex,
sizeof(hex) - 1,
"%02X", c);
27425 result.append(hex,
static_cast<size_t>(len));
27436inline std::string decode_url(
const std::string &s,
27437 bool convert_plus_to_space) {
27438 std::string result;
27440 for (
size_t i = 0; i < s.size(); i++) {
27441 if (s[i] ==
'%' && i + 1 < s.size()) {
27442 if (s[i + 1] ==
'u') {
27444 if (from_hex_to_i(s, i + 2, 4, val)) {
27447 size_t len = to_utf8(val, buff);
27448 if (len > 0) { result.append(buff, len); }
27455 if (from_hex_to_i(s, i + 1, 2, val)) {
27457 result +=
static_cast<char>(val);
27463 }
else if (convert_plus_to_space && s[i] ==
'+') {
27473inline void read_file(
const std::string &path, std::string &out) {
27474 std::ifstream fs(path, std::ios_base::binary);
27475 fs.seekg(0, std::ios_base::end);
27476 auto size = fs.tellg();
27478 out.resize(
static_cast<size_t>(size));
27479 fs.read(&out[0],
static_cast<std::streamsize
>(size));
27482inline std::string file_extension(
const std::string &path) {
27484 static auto re = std::regex(
"\\.([a-zA-Z0-9]+)$");
27485 if (std::regex_search(path, m, re)) {
return m[1].str(); }
27486 return std::string();
27489inline bool is_space_or_tab(
char c) {
return c ==
' ' || c ==
'\t'; }
27491inline std::pair<size_t, size_t> trim(
const char *b,
const char *e,
size_t left,
27493 while (b + left < e && is_space_or_tab(b[left])) {
27496 while (right > 0 && is_space_or_tab(b[right - 1])) {
27499 return std::make_pair(left, right);
27502inline std::string trim_copy(
const std::string &s) {
27503 auto r = trim(s.data(), s.data() + s.size(), 0, s.size());
27504 return s.substr(r.first, r.second - r.first);
27507inline std::string trim_double_quotes_copy(
const std::string &s) {
27508 if (s.length() >= 2 && s.front() ==
'"' && s.back() ==
'"') {
27509 return s.substr(1, s.size() - 2);
27515divide(
const char *data, std::size_t size,
char d,
27516 std::function<
void(
const char *, std::size_t,
const char *, std::size_t)>
27518 const auto it = std::find(data, data + size, d);
27519 const auto found =
static_cast<std::size_t
>(it != data + size);
27520 const auto lhs_data = data;
27521 const auto lhs_size =
static_cast<std::size_t
>(it - data);
27522 const auto rhs_data = it + found;
27523 const auto rhs_size = size - lhs_size - found;
27525 fn(lhs_data, lhs_size, rhs_data, rhs_size);
27529divide(
const std::string &str,
char d,
27530 std::function<
void(
const char *, std::size_t,
const char *, std::size_t)>
27532 divide(str.data(), str.size(), d, std::move(fn));
27535inline void split(
const char *b,
const char *e,
char d,
27536 std::function<
void(
const char *,
const char *)> fn) {
27537 return split(b, e, d, (std::numeric_limits<size_t>::max)(), std::move(fn));
27540inline void split(
const char *b,
const char *e,
char d,
size_t m,
27541 std::function<
void(
const char *,
const char *)> fn) {
27546 while (e ? (b + i < e) : (b[i] !=
'\0')) {
27547 if (b[i] == d && count < m) {
27548 auto r = trim(b, e, beg, i);
27549 if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
27557 auto r = trim(b, e, beg, i);
27558 if (r.first < r.second) { fn(&b[r.first], &b[r.second]); }
27562inline stream_line_reader::stream_line_reader(Stream &strm,
char *fixed_buffer,
27563 size_t fixed_buffer_size)
27564 : strm_(strm), fixed_buffer_(fixed_buffer),
27565 fixed_buffer_size_(fixed_buffer_size) {}
27567inline const char *stream_line_reader::ptr()
const {
27568 if (glowable_buffer_.empty()) {
27569 return fixed_buffer_;
27571 return glowable_buffer_.data();
27575inline size_t stream_line_reader::size()
const {
27576 if (glowable_buffer_.empty()) {
27577 return fixed_buffer_used_size_;
27579 return glowable_buffer_.size();
27583inline bool stream_line_reader::end_with_crlf()
const {
27584 auto end = ptr() + size();
27585 return size() >= 2 && end[-2] ==
'\r' && end[-1] ==
'\n';
27588inline bool stream_line_reader::getline() {
27589 fixed_buffer_used_size_ = 0;
27590 glowable_buffer_.clear();
27592 for (
size_t i = 0;; i++) {
27594 auto n = strm_.read(&
byte, 1);
27598 }
else if (n == 0) {
27608 if (
byte ==
'\n') {
break; }
27614inline void stream_line_reader::append(
char c) {
27615 if (fixed_buffer_used_size_ < fixed_buffer_size_ - 1) {
27616 fixed_buffer_[fixed_buffer_used_size_++] = c;
27617 fixed_buffer_[fixed_buffer_used_size_] =
'\0';
27619 if (glowable_buffer_.empty()) {
27620 assert(fixed_buffer_[fixed_buffer_used_size_] ==
'\0');
27621 glowable_buffer_.assign(fixed_buffer_, fixed_buffer_used_size_);
27623 glowable_buffer_ += c;
27627inline mmap::mmap(
const char *path)
27629 : hFile_(NULL), hMapping_(NULL)
27634 size_(0), addr_(
nullptr) {
27638inline mmap::~mmap() { close(); }
27640inline bool mmap::open(
const char *path) {
27644 std::wstring wpath;
27645 for (
size_t i = 0; i < strlen(path); i++) {
27649 hFile_ = ::CreateFile2(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ,
27650 OPEN_EXISTING, NULL);
27652 if (hFile_ == INVALID_HANDLE_VALUE) {
return false; }
27654 LARGE_INTEGER size{};
27655 if (!::GetFileSizeEx(hFile_, &size)) {
return false; }
27656 size_ =
static_cast<size_t>(size.QuadPart);
27659 ::CreateFileMappingFromApp(hFile_, NULL, PAGE_READONLY, size_, NULL);
27661 if (hMapping_ == NULL) {
27666 addr_ = ::MapViewOfFileFromApp(hMapping_, FILE_MAP_READ, 0, 0);
27668 fd_ = ::open(path, O_RDONLY);
27669 if (fd_ == -1) {
return false; }
27672 if (fstat(fd_, &sb) == -1) {
27676 size_ =
static_cast<size_t>(sb.st_size);
27678 addr_ = ::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0);
27681 if (addr_ ==
nullptr) {
27689inline bool mmap::is_open()
const {
return addr_ !=
nullptr; }
27691inline size_t mmap::size()
const {
return size_; }
27693inline const char *mmap::data()
const {
27694 return static_cast<const char *
>(addr_);
27697inline void mmap::close() {
27700 ::UnmapViewOfFile(addr_);
27705 ::CloseHandle(hMapping_);
27709 if (hFile_ != INVALID_HANDLE_VALUE) {
27710 ::CloseHandle(hFile_);
27711 hFile_ = INVALID_HANDLE_VALUE;
27714 if (addr_ !=
nullptr) {
27715 munmap(addr_, size_);
27726inline int close_socket(socket_t sock) {
27728 return closesocket(sock);
27730 return close(sock);
27734template <
typename T>
inline ssize_t handle_EINTR(T fn) {
27738 if (res < 0 && errno == EINTR) {
continue; }
27744inline ssize_t read_socket(socket_t sock,
void *ptr,
size_t size,
int flags) {
27745 return handle_EINTR([&]() {
27748 static_cast<char *
>(ptr),
static_cast<int>(size),
27756inline ssize_t send_socket(socket_t sock,
const void *ptr,
size_t size,
27758 return handle_EINTR([&]() {
27761 static_cast<const char *
>(ptr),
static_cast<int>(size),
27769inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) {
27770#ifdef CPPHTTPLIB_USE_POLL
27771 struct pollfd pfd_read;
27772 pfd_read.fd = sock;
27773 pfd_read.events = POLLIN;
27775 auto timeout =
static_cast<int>(sec * 1000 + usec / 1000);
27777 return handle_EINTR([&]() {
return poll(&pfd_read, 1, timeout); });
27780 if (sock >= FD_SETSIZE) {
return -1; }
27785 FD_SET(sock, &fds);
27788 tv.tv_sec =
static_cast<long>(sec);
27789 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(usec);
27791 return handle_EINTR([&]() {
27792 return select(
static_cast<int>(sock + 1), &fds,
nullptr,
nullptr, &tv);
27797inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) {
27798#ifdef CPPHTTPLIB_USE_POLL
27799 struct pollfd pfd_read;
27800 pfd_read.fd = sock;
27801 pfd_read.events = POLLOUT;
27803 auto timeout =
static_cast<int>(sec * 1000 + usec / 1000);
27805 return handle_EINTR([&]() {
return poll(&pfd_read, 1, timeout); });
27808 if (sock >= FD_SETSIZE) {
return -1; }
27813 FD_SET(sock, &fds);
27816 tv.tv_sec =
static_cast<long>(sec);
27817 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(usec);
27819 return handle_EINTR([&]() {
27820 return select(
static_cast<int>(sock + 1),
nullptr, &fds,
nullptr, &tv);
27825inline Error wait_until_socket_is_ready(socket_t sock, time_t sec,
27827#ifdef CPPHTTPLIB_USE_POLL
27828 struct pollfd pfd_read;
27829 pfd_read.fd = sock;
27830 pfd_read.events = POLLIN | POLLOUT;
27832 auto timeout =
static_cast<int>(sec * 1000 + usec / 1000);
27834 auto poll_res = handle_EINTR([&]() {
return poll(&pfd_read, 1, timeout); });
27836 if (poll_res == 0) {
return Error::ConnectionTimeout; }
27838 if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) {
27840 socklen_t len =
sizeof(
error);
27841 auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR,
27842 reinterpret_cast<char *
>(&error), &len);
27843 auto successful = res >= 0 && !
error;
27844 return successful ? Error::Success : Error::Connection;
27847 return Error::Connection;
27850 if (sock >= FD_SETSIZE) {
return Error::Connection; }
27855 FD_SET(sock, &fdsr);
27861 tv.tv_sec =
static_cast<long>(sec);
27862 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(usec);
27864 auto ret = handle_EINTR([&]() {
27865 return select(
static_cast<int>(sock + 1), &fdsr, &fdsw, &fdse, &tv);
27868 if (ret == 0) {
return Error::ConnectionTimeout; }
27870 if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) {
27872 socklen_t len =
sizeof(
error);
27873 auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR,
27874 reinterpret_cast<char *
>(&error), &len);
27875 auto successful = res >= 0 && !
error;
27876 return successful ? Error::Success : Error::Connection;
27878 return Error::Connection;
27882inline bool is_socket_alive(socket_t sock) {
27883 const auto val = detail::select_read(sock, 0, 0);
27886 }
else if (val < 0 && errno == EBADF) {
27890 return detail::read_socket(sock, &buf[0],
sizeof(buf), MSG_PEEK) > 0;
27895 SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec,
27896 time_t write_timeout_sec, time_t write_timeout_usec);
27899 bool is_readable()
const override;
27900 bool is_writable()
const override;
27901 ssize_t read(
char *ptr,
size_t size)
override;
27902 ssize_t write(
const char *ptr,
size_t size)
override;
27903 void get_remote_ip_and_port(std::string &ip,
int &port)
const override;
27904 void get_local_ip_and_port(std::string &ip,
int &port)
const override;
27905 socket_t socket()
const override;
27909 time_t read_timeout_sec_;
27910 time_t read_timeout_usec_;
27911 time_t write_timeout_sec_;
27912 time_t write_timeout_usec_;
27914 std::vector<char> read_buff_;
27915 size_t read_buff_off_ = 0;
27916 size_t read_buff_content_size_ = 0;
27918 static const size_t read_buff_size_ = 1024l * 4;
27921#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
27922class SSLSocketStream final :
public Stream {
27924 SSLSocketStream(socket_t sock, SSL *ssl, time_t read_timeout_sec,
27925 time_t read_timeout_usec, time_t write_timeout_sec,
27926 time_t write_timeout_usec);
27927 ~SSLSocketStream()
override;
27929 bool is_readable()
const override;
27930 bool is_writable()
const override;
27931 ssize_t read(
char *ptr,
size_t size)
override;
27932 ssize_t write(
const char *ptr,
size_t size)
override;
27933 void get_remote_ip_and_port(std::string &ip,
int &port)
const override;
27934 void get_local_ip_and_port(std::string &ip,
int &port)
const override;
27935 socket_t socket()
const override;
27940 time_t read_timeout_sec_;
27941 time_t read_timeout_usec_;
27942 time_t write_timeout_sec_;
27943 time_t write_timeout_usec_;
27947inline bool keep_alive(socket_t sock, time_t keep_alive_timeout_sec) {
27948 using namespace std::chrono;
27949 auto start = steady_clock::now();
27951 auto val = select_read(sock, 0, 10000);
27954 }
else if (val == 0) {
27955 auto current = steady_clock::now();
27956 auto duration = duration_cast<milliseconds>(current - start);
27957 auto timeout = keep_alive_timeout_sec * 1000;
27958 if (duration.count() > timeout) {
return false; }
27959 std::this_thread::sleep_for(std::chrono::milliseconds(1));
27966template <
typename T>
27968process_server_socket_core(
const std::atomic<socket_t> &svr_sock, socket_t sock,
27969 size_t keep_alive_max_count,
27970 time_t keep_alive_timeout_sec, T callback) {
27971 assert(keep_alive_max_count > 0);
27973 auto count = keep_alive_max_count;
27974 while (svr_sock != INVALID_SOCKET && count > 0 &&
27975 keep_alive(sock, keep_alive_timeout_sec)) {
27976 auto close_connection = count == 1;
27977 auto connection_closed =
false;
27978 ret = callback(close_connection, connection_closed);
27979 if (!ret || connection_closed) {
break; }
27985template <
typename T>
27987process_server_socket(
const std::atomic<socket_t> &svr_sock, socket_t sock,
27988 size_t keep_alive_max_count,
27989 time_t keep_alive_timeout_sec, time_t read_timeout_sec,
27990 time_t read_timeout_usec, time_t write_timeout_sec,
27991 time_t write_timeout_usec, T callback) {
27992 return process_server_socket_core(
27993 svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec,
27994 [&](
bool close_connection,
bool &connection_closed) {
27995 SocketStream strm(sock, read_timeout_sec, read_timeout_usec,
27996 write_timeout_sec, write_timeout_usec);
27997 return callback(strm, close_connection, connection_closed);
28001inline bool process_client_socket(socket_t sock, time_t read_timeout_sec,
28002 time_t read_timeout_usec,
28003 time_t write_timeout_sec,
28004 time_t write_timeout_usec,
28005 std::function<
bool(Stream &)> callback) {
28006 SocketStream strm(sock, read_timeout_sec, read_timeout_usec,
28007 write_timeout_sec, write_timeout_usec);
28008 return callback(strm);
28011inline int shutdown_socket(socket_t sock) {
28013 return shutdown(sock, SD_BOTH);
28015 return shutdown(sock, SHUT_RDWR);
28019template <
typename BindOrConnect>
28020socket_t create_socket(
const std::string &host,
const std::string &ip,
int port,
28021 int address_family,
int socket_flags,
bool tcp_nodelay,
28022 SocketOptions socket_options,
28023 BindOrConnect bind_or_connect) {
28025 const char *node =
nullptr;
28026 struct addrinfo hints;
28027 struct addrinfo *result;
28029 memset(&hints, 0,
sizeof(
struct addrinfo));
28030 hints.ai_socktype = SOCK_STREAM;
28031 hints.ai_protocol = 0;
28036 hints.ai_family = AF_UNSPEC;
28037 hints.ai_flags = AI_NUMERICHOST;
28039 if (!host.empty()) { node = host.c_str(); }
28040 hints.ai_family = address_family;
28041 hints.ai_flags = socket_flags;
28045 if (hints.ai_family == AF_UNIX) {
28046 const auto addrlen = host.length();
28047 if (addrlen >
sizeof(sockaddr_un::sun_path)) {
return INVALID_SOCKET; }
28049 auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol);
28050 if (sock != INVALID_SOCKET) {
28051 sockaddr_un addr{};
28052 addr.sun_family = AF_UNIX;
28053 std::copy(host.begin(), host.end(), addr.sun_path);
28055 hints.ai_addr =
reinterpret_cast<sockaddr *
>(&addr);
28056 hints.ai_addrlen =
static_cast<socklen_t
>(
28057 sizeof(addr) -
sizeof(addr.sun_path) + addrlen);
28059 fcntl(sock, F_SETFD, FD_CLOEXEC);
28060 if (socket_options) { socket_options(sock); }
28062 if (!bind_or_connect(sock, hints)) {
28063 close_socket(sock);
28064 sock = INVALID_SOCKET;
28071 auto service = std::to_string(port);
28073 if (getaddrinfo(node, service.c_str(), &hints, &result)) {
28074#if defined __linux__ && !defined __ANDROID__
28077 return INVALID_SOCKET;
28080 for (
auto rp = result; rp; rp = rp->ai_next) {
28084 WSASocketW(rp->ai_family, rp->ai_socktype, rp->ai_protocol,
nullptr, 0,
28085 WSA_FLAG_NO_HANDLE_INHERIT | WSA_FLAG_OVERLAPPED);
28100 if (sock == INVALID_SOCKET) {
28101 sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
28104 auto sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
28106 if (sock == INVALID_SOCKET) {
continue; }
28109 if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) {
28110 close_socket(sock);
28118 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
28119 reinterpret_cast<const char *
>(&yes),
sizeof(yes));
28121 setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
28122 reinterpret_cast<const void *
>(&yes),
sizeof(yes));
28126 if (socket_options) { socket_options(sock); }
28128 if (rp->ai_family == AF_INET6) {
28131 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
28132 reinterpret_cast<const char *
>(&no),
sizeof(no));
28134 setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
28135 reinterpret_cast<const void *
>(&no),
sizeof(no));
28140 if (bind_or_connect(sock, *rp)) {
28141 freeaddrinfo(result);
28145 close_socket(sock);
28148 freeaddrinfo(result);
28149 return INVALID_SOCKET;
28152inline void set_nonblocking(socket_t sock,
bool nonblocking) {
28154 auto flags = nonblocking ? 1UL : 0UL;
28155 ioctlsocket(sock, FIONBIO, &flags);
28157 auto flags = fcntl(sock, F_GETFL, 0);
28158 fcntl(sock, F_SETFL,
28159 nonblocking ? (flags | O_NONBLOCK) : (flags & (~O_NONBLOCK)));
28163inline bool is_connection_error() {
28165 return WSAGetLastError() != WSAEWOULDBLOCK;
28167 return errno != EINPROGRESS;
28171inline bool bind_ip_address(socket_t sock,
const std::string &host) {
28172 struct addrinfo hints;
28173 struct addrinfo *result;
28175 memset(&hints, 0,
sizeof(
struct addrinfo));
28176 hints.ai_family = AF_UNSPEC;
28177 hints.ai_socktype = SOCK_STREAM;
28178 hints.ai_protocol = 0;
28180 if (getaddrinfo(host.c_str(),
"0", &hints, &result)) {
return false; }
28183 for (
auto rp = result; rp; rp = rp->ai_next) {
28184 const auto &ai = *rp;
28185 if (!::bind(sock, ai.ai_addr,
static_cast<socklen_t
>(ai.ai_addrlen))) {
28191 freeaddrinfo(result);
28195#if !defined _WIN32 && !defined ANDROID && !defined _AIX && !defined __MVS__
28200inline std::string if2ip(
int address_family,
const std::string &ifn) {
28201 struct ifaddrs *ifap;
28203 std::string addr_candidate;
28204 for (
auto ifa = ifap; ifa; ifa = ifa->ifa_next) {
28205 if (ifa->ifa_addr && ifn == ifa->ifa_name &&
28206 (AF_UNSPEC == address_family ||
28207 ifa->ifa_addr->sa_family == address_family)) {
28208 if (ifa->ifa_addr->sa_family == AF_INET) {
28209 auto sa =
reinterpret_cast<struct sockaddr_in *
>(ifa->ifa_addr);
28210 char buf[INET_ADDRSTRLEN];
28211 if (inet_ntop(AF_INET, &sa->sin_addr, buf, INET_ADDRSTRLEN)) {
28213 return std::string(buf, INET_ADDRSTRLEN);
28215 }
else if (ifa->ifa_addr->sa_family == AF_INET6) {
28216 auto sa =
reinterpret_cast<struct sockaddr_in6 *
>(ifa->ifa_addr);
28217 if (!IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) {
28218 char buf[INET6_ADDRSTRLEN] = {};
28219 if (inet_ntop(AF_INET6, &sa->sin6_addr, buf, INET6_ADDRSTRLEN)) {
28221 auto s6_addr_head = sa->sin6_addr.s6_addr[0];
28222 if (s6_addr_head == 0xfc || s6_addr_head == 0xfd) {
28223 addr_candidate = std::string(buf, INET6_ADDRSTRLEN);
28226 return std::string(buf, INET6_ADDRSTRLEN);
28234 return addr_candidate;
28238inline socket_t create_client_socket(
28239 const std::string &host,
const std::string &ip,
int port,
28240 int address_family,
bool tcp_nodelay, SocketOptions socket_options,
28241 time_t connection_timeout_sec, time_t connection_timeout_usec,
28242 time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
28243 time_t write_timeout_usec,
const std::string &intf, Error &error) {
28244 auto sock = create_socket(
28245 host, ip, port, address_family, 0, tcp_nodelay, std::move(socket_options),
28246 [&](socket_t sock2,
struct addrinfo &ai) ->
bool {
28247 if (!intf.empty()) {
28249 auto ip_from_if = if2ip(address_family, intf);
28250 if (ip_from_if.empty()) { ip_from_if = intf; }
28251 if (!bind_ip_address(sock2, ip_from_if)) {
28252 error = Error::BindIPAddress;
28258 set_nonblocking(sock2,
true);
28261 ::connect(sock2, ai.ai_addr,
static_cast<socklen_t
>(ai.ai_addrlen));
28264 if (is_connection_error()) {
28265 error = Error::Connection;
28268 error = wait_until_socket_is_ready(sock2, connection_timeout_sec,
28269 connection_timeout_usec);
28270 if (error != Error::Success) {
return false; }
28273 set_nonblocking(sock2,
false);
28277 auto timeout =
static_cast<uint32_t
>(read_timeout_sec * 1000 +
28278 read_timeout_usec / 1000);
28279 setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO,
28280 reinterpret_cast<const char *
>(&timeout),
sizeof(timeout));
28283 tv.tv_sec =
static_cast<long>(read_timeout_sec);
28284 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(read_timeout_usec);
28285 setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO,
28286 reinterpret_cast<const void *
>(&tv),
sizeof(tv));
28292 auto timeout =
static_cast<uint32_t
>(write_timeout_sec * 1000 +
28293 write_timeout_usec / 1000);
28294 setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO,
28295 reinterpret_cast<const char *
>(&timeout),
sizeof(timeout));
28298 tv.tv_sec =
static_cast<long>(write_timeout_sec);
28299 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(write_timeout_usec);
28300 setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO,
28301 reinterpret_cast<const void *
>(&tv),
sizeof(tv));
28305 error = Error::Success;
28309 if (sock != INVALID_SOCKET) {
28310 error = Error::Success;
28312 if (error == Error::Success) {
error = Error::Connection; }
28318inline bool get_ip_and_port(
const struct sockaddr_storage &addr,
28319 socklen_t addr_len, std::string &ip,
int &port) {
28320 if (addr.ss_family == AF_INET) {
28321 port = ntohs(
reinterpret_cast<const struct sockaddr_in *
>(&addr)->sin_port);
28322 }
else if (addr.ss_family == AF_INET6) {
28324 ntohs(
reinterpret_cast<const struct sockaddr_in6 *
>(&addr)->sin6_port);
28329 std::array<char, NI_MAXHOST> ipstr{};
28330 if (getnameinfo(
reinterpret_cast<const struct sockaddr *
>(&addr), addr_len,
28331 ipstr.data(),
static_cast<socklen_t
>(ipstr.size()),
nullptr,
28332 0, NI_NUMERICHOST)) {
28340inline void get_local_ip_and_port(socket_t sock, std::string &ip,
int &port) {
28341 struct sockaddr_storage addr;
28342 socklen_t addr_len =
sizeof(addr);
28343 if (!getsockname(sock,
reinterpret_cast<struct sockaddr *
>(&addr),
28345 get_ip_and_port(addr, addr_len, ip, port);
28349inline void get_remote_ip_and_port(socket_t sock, std::string &ip,
int &port) {
28350 struct sockaddr_storage addr;
28351 socklen_t addr_len =
sizeof(addr);
28353 if (!getpeername(sock,
reinterpret_cast<struct sockaddr *
>(&addr),
28356 if (addr.ss_family == AF_UNIX) {
28357#if defined(__linux__)
28358 struct ucred ucred;
28359 socklen_t len =
sizeof(ucred);
28360 if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == 0) {
28363#elif defined(SOL_LOCAL) && defined(SO_PEERPID)
28365 socklen_t len =
sizeof(pid);
28366 if (getsockopt(sock, SOL_LOCAL, SO_PEERPID, &pid, &len) == 0) {
28373 get_ip_and_port(addr, addr_len, ip, port);
28377inline constexpr unsigned int str2tag_core(
const char *s,
size_t l,
28384 (((std::numeric_limits<unsigned int>::max)() >> 6) &
28386 static_cast<unsigned char>(*s));
28389inline unsigned int str2tag(
const std::string &s) {
28390 return str2tag_core(s.data(), s.size(), 0);
28395inline constexpr unsigned int operator"" _t(
const char *s,
size_t l) {
28396 return str2tag_core(s, l, 0);
28402find_content_type(
const std::string &path,
28403 const std::map<std::string, std::string> &user_data,
28404 const std::string &default_content_type) {
28405 auto ext = file_extension(path);
28407 auto it = user_data.find(ext);
28408 if (it != user_data.end()) {
return it->second; }
28410 using udl::operator
""_t;
28412 switch (str2tag(ext)) {
28413 default:
return default_content_type;
28415 case "css"_t:
return "text/css";
28416 case "csv"_t:
return "text/csv";
28418 case "html"_t:
return "text/html";
28420 case "mjs"_t:
return "text/javascript";
28421 case "txt"_t:
return "text/plain";
28422 case "vtt"_t:
return "text/vtt";
28424 case "apng"_t:
return "image/apng";
28425 case "avif"_t:
return "image/avif";
28426 case "bmp"_t:
return "image/bmp";
28427 case "gif"_t:
return "image/gif";
28428 case "png"_t:
return "image/png";
28429 case "svg"_t:
return "image/svg+xml";
28430 case "webp"_t:
return "image/webp";
28431 case "ico"_t:
return "image/x-icon";
28432 case "tif"_t:
return "image/tiff";
28433 case "tiff"_t:
return "image/tiff";
28435 case "jpeg"_t:
return "image/jpeg";
28437 case "mp4"_t:
return "video/mp4";
28438 case "mpeg"_t:
return "video/mpeg";
28439 case "webm"_t:
return "video/webm";
28441 case "mp3"_t:
return "audio/mp3";
28442 case "mpga"_t:
return "audio/mpeg";
28443 case "weba"_t:
return "audio/webm";
28444 case "wav"_t:
return "audio/wave";
28446 case "otf"_t:
return "font/otf";
28447 case "ttf"_t:
return "font/ttf";
28448 case "woff"_t:
return "font/woff";
28449 case "woff2"_t:
return "font/woff2";
28451 case "7z"_t:
return "application/x-7z-compressed";
28452 case "atom"_t:
return "application/atom+xml";
28453 case "pdf"_t:
return "application/pdf";
28454 case "json"_t:
return "application/json";
28455 case "rss"_t:
return "application/rss+xml";
28456 case "tar"_t:
return "application/x-tar";
28458 case "xhtml"_t:
return "application/xhtml+xml";
28459 case "xslt"_t:
return "application/xslt+xml";
28460 case "xml"_t:
return "application/xml";
28461 case "gz"_t:
return "application/gzip";
28462 case "zip"_t:
return "application/zip";
28463 case "wasm"_t:
return "application/wasm";
28467inline bool can_compress_content_type(
const std::string &content_type) {
28468 using udl::operator
""_t;
28470 auto tag = str2tag(content_type);
28473 case "image/svg+xml"_t:
28474 case "application/javascript"_t:
28475 case "application/json"_t:
28476 case "application/xml"_t:
28477 case "application/protobuf"_t:
28478 case "application/xhtml+xml"_t:
return true;
28481 return !content_type.rfind(
"text/", 0) && tag !=
"text/event-stream"_t;
28485inline EncodingType encoding_type(
const Request &req,
const Response &res) {
28487 detail::can_compress_content_type(res.get_header_value(
"Content-Type"));
28488 if (!ret) {
return EncodingType::None; }
28490 const auto &s = req.get_header_value(
"Accept-Encoding");
28493#ifdef CPPHTTPLIB_BROTLI_SUPPORT
28495 ret = s.find(
"br") != std::string::npos;
28496 if (ret) {
return EncodingType::Brotli; }
28499#ifdef CPPHTTPLIB_ZLIB_SUPPORT
28501 ret = s.find(
"gzip") != std::string::npos;
28502 if (ret) {
return EncodingType::Gzip; }
28505 return EncodingType::None;
28508inline bool nocompressor::compress(
const char *data,
size_t data_length,
28509 bool , Callback callback) {
28510 if (!data_length) {
return true; }
28511 return callback(data, data_length);
28514#ifdef CPPHTTPLIB_ZLIB_SUPPORT
28515inline gzip_compressor::gzip_compressor() {
28516 std::memset(&strm_, 0,
sizeof(strm_));
28517 strm_.zalloc = Z_NULL;
28518 strm_.zfree = Z_NULL;
28519 strm_.opaque = Z_NULL;
28521 is_valid_ = deflateInit2(&strm_, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8,
28522 Z_DEFAULT_STRATEGY) == Z_OK;
28525inline gzip_compressor::~gzip_compressor() { deflateEnd(&strm_); }
28527inline bool gzip_compressor::compress(
const char *data,
size_t data_length,
28528 bool last, Callback callback) {
28532 constexpr size_t max_avail_in =
28533 (std::numeric_limits<
decltype(strm_.avail_in)>::max)();
28535 strm_.avail_in =
static_cast<decltype(strm_.avail_in)
>(
28536 (std::min)(data_length, max_avail_in));
28537 strm_.next_in =
const_cast<Bytef *
>(
reinterpret_cast<const Bytef *
>(data));
28539 data_length -= strm_.avail_in;
28540 data += strm_.avail_in;
28542 auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH;
28545 std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
28547 strm_.avail_out =
static_cast<uInt
>(buff.size());
28548 strm_.next_out =
reinterpret_cast<Bytef *
>(buff.data());
28550 ret = deflate(&strm_, flush);
28551 if (ret == Z_STREAM_ERROR) {
return false; }
28553 if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
28556 }
while (strm_.avail_out == 0);
28558 assert((flush == Z_FINISH && ret == Z_STREAM_END) ||
28559 (flush == Z_NO_FLUSH && ret == Z_OK));
28560 assert(strm_.avail_in == 0);
28561 }
while (data_length > 0);
28566inline gzip_decompressor::gzip_decompressor() {
28567 std::memset(&strm_, 0,
sizeof(strm_));
28568 strm_.zalloc = Z_NULL;
28569 strm_.zfree = Z_NULL;
28570 strm_.opaque = Z_NULL;
28576 is_valid_ = inflateInit2(&strm_, 32 + 15) == Z_OK;
28579inline gzip_decompressor::~gzip_decompressor() { inflateEnd(&strm_); }
28581inline bool gzip_decompressor::is_valid()
const {
return is_valid_; }
28583inline bool gzip_decompressor::decompress(
const char *data,
size_t data_length,
28584 Callback callback) {
28590 constexpr size_t max_avail_in =
28591 (std::numeric_limits<
decltype(strm_.avail_in)>::max)();
28593 strm_.avail_in =
static_cast<decltype(strm_.avail_in)
>(
28594 (std::min)(data_length, max_avail_in));
28595 strm_.next_in =
const_cast<Bytef *
>(
reinterpret_cast<const Bytef *
>(data));
28597 data_length -= strm_.avail_in;
28598 data += strm_.avail_in;
28600 std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
28601 while (strm_.avail_in > 0 && ret == Z_OK) {
28602 strm_.avail_out =
static_cast<uInt
>(buff.size());
28603 strm_.next_out =
reinterpret_cast<Bytef *
>(buff.data());
28605 ret = inflate(&strm_, Z_NO_FLUSH);
28607 assert(ret != Z_STREAM_ERROR);
28611 case Z_MEM_ERROR: inflateEnd(&strm_);
return false;
28614 if (!callback(buff.data(), buff.size() - strm_.avail_out)) {
28619 if (ret != Z_OK && ret != Z_STREAM_END) {
return false; }
28621 }
while (data_length > 0);
28627#ifdef CPPHTTPLIB_BROTLI_SUPPORT
28628inline brotli_compressor::brotli_compressor() {
28629 state_ = BrotliEncoderCreateInstance(
nullptr,
nullptr,
nullptr);
28632inline brotli_compressor::~brotli_compressor() {
28633 BrotliEncoderDestroyInstance(state_);
28636inline bool brotli_compressor::compress(
const char *data,
size_t data_length,
28637 bool last, Callback callback) {
28638 std::array<uint8_t, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
28640 auto operation = last ? BROTLI_OPERATION_FINISH : BROTLI_OPERATION_PROCESS;
28641 auto available_in = data_length;
28642 auto next_in =
reinterpret_cast<const uint8_t *
>(data);
28646 if (BrotliEncoderIsFinished(state_)) {
break; }
28648 if (!available_in) {
break; }
28651 auto available_out = buff.size();
28652 auto next_out = buff.data();
28654 if (!BrotliEncoderCompressStream(state_, operation, &available_in, &next_in,
28655 &available_out, &next_out,
nullptr)) {
28659 auto output_bytes = buff.size() - available_out;
28660 if (output_bytes) {
28661 callback(
reinterpret_cast<const char *
>(buff.data()), output_bytes);
28668inline brotli_decompressor::brotli_decompressor() {
28669 decoder_s = BrotliDecoderCreateInstance(0, 0, 0);
28670 decoder_r = decoder_s ? BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT
28671 : BROTLI_DECODER_RESULT_ERROR;
28674inline brotli_decompressor::~brotli_decompressor() {
28675 if (decoder_s) { BrotliDecoderDestroyInstance(decoder_s); }
28678inline bool brotli_decompressor::is_valid()
const {
return decoder_s; }
28680inline bool brotli_decompressor::decompress(
const char *data,
28681 size_t data_length,
28682 Callback callback) {
28683 if (decoder_r == BROTLI_DECODER_RESULT_SUCCESS ||
28684 decoder_r == BROTLI_DECODER_RESULT_ERROR) {
28688 auto next_in =
reinterpret_cast<const uint8_t *
>(data);
28689 size_t avail_in = data_length;
28692 decoder_r = BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;
28694 std::array<char, CPPHTTPLIB_COMPRESSION_BUFSIZ> buff{};
28695 while (decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
28696 char *next_out = buff.data();
28697 size_t avail_out = buff.size();
28699 decoder_r = BrotliDecoderDecompressStream(
28700 decoder_s, &avail_in, &next_in, &avail_out,
28701 reinterpret_cast<uint8_t **
>(&next_out), &total_out);
28703 if (decoder_r == BROTLI_DECODER_RESULT_ERROR) {
return false; }
28705 if (!callback(buff.data(), buff.size() - avail_out)) {
return false; }
28708 return decoder_r == BROTLI_DECODER_RESULT_SUCCESS ||
28709 decoder_r == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
28713inline bool has_header(
const Headers &headers,
const std::string &key) {
28714 return headers.find(key) != headers.end();
28717inline const char *get_header_value(
const Headers &headers,
28718 const std::string &key,
size_t id,
28720 auto rng = headers.equal_range(key);
28721 auto it = rng.first;
28722 std::advance(it,
static_cast<ssize_t
>(
id));
28723 if (it != rng.second) {
return it->second.c_str(); }
28727inline bool compare_case_ignore(
const std::string &a,
const std::string &b) {
28728 if (a.size() != b.size()) {
return false; }
28729 for (
size_t i = 0; i < b.size(); i++) {
28730 if (::tolower(a[i]) != ::tolower(b[i])) {
return false; }
28735template <
typename T>
28736inline bool parse_header(
const char *beg,
const char *end, T fn) {
28738 while (beg < end && is_space_or_tab(end[-1])) {
28743 while (p < end && *p !=
':') {
28747 if (p == end) {
return false; }
28751 if (*p++ !=
':') {
return false; }
28753 while (p < end && is_space_or_tab(*p)) {
28758 auto key_len = key_end - beg;
28759 if (!key_len) {
return false; }
28761 auto key = std::string(beg, key_end);
28762 auto val = compare_case_ignore(key,
"Location")
28763 ? std::string(p, end)
28764 : decode_url(std::
string(p, end), false);
28772inline bool read_headers(Stream &strm, Headers &headers) {
28773 const auto bufsiz = 2048;
28775 stream_line_reader line_reader(strm, buf, bufsiz);
28778 if (!line_reader.getline()) {
return false; }
28781 auto line_terminator_len = 2;
28782 if (line_reader.end_with_crlf()) {
28784 if (line_reader.size() == 2) {
break; }
28785#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
28788 if (line_reader.size() == 1) {
break; }
28789 line_terminator_len = 1;
28797 if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) {
return false; }
28800 auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
28802 parse_header(line_reader.ptr(), end,
28803 [&](
const std::string &key,
const std::string &val) {
28804 headers.emplace(key, val);
28811inline bool read_content_with_length(Stream &strm, uint64_t len,
28813 ContentReceiverWithProgress out) {
28814 char buf[CPPHTTPLIB_RECV_BUFSIZ];
28818 auto read_len =
static_cast<size_t>(len - r);
28819 auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ));
28820 if (n <= 0) {
return false; }
28822 if (!out(buf,
static_cast<size_t>(n), r, len)) {
return false; }
28823 r +=
static_cast<uint64_t
>(n);
28826 if (!progress(r, len)) {
return false; }
28833inline void skip_content_with_length(Stream &strm, uint64_t len) {
28834 char buf[CPPHTTPLIB_RECV_BUFSIZ];
28837 auto read_len =
static_cast<size_t>(len - r);
28838 auto n = strm.read(buf, (std::min)(read_len, CPPHTTPLIB_RECV_BUFSIZ));
28839 if (n <= 0) {
return; }
28840 r +=
static_cast<uint64_t
>(n);
28844inline bool read_content_without_length(Stream &strm,
28845 ContentReceiverWithProgress out) {
28846 char buf[CPPHTTPLIB_RECV_BUFSIZ];
28849 auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ);
28850 if (n <= 0) {
return true; }
28852 if (!out(buf,
static_cast<size_t>(n), r, 0)) {
return false; }
28853 r +=
static_cast<uint64_t
>(n);
28859template <
typename T>
28860inline bool read_content_chunked(Stream &strm, T &x,
28861 ContentReceiverWithProgress out) {
28862 const auto bufsiz = 16;
28865 stream_line_reader line_reader(strm, buf, bufsiz);
28867 if (!line_reader.getline()) {
return false; }
28869 unsigned long chunk_len;
28873 chunk_len = std::strtoul(line_reader.ptr(), &end_ptr, 16);
28875 if (end_ptr == line_reader.ptr()) {
return false; }
28876 if (chunk_len == ULONG_MAX) {
return false; }
28878 if (chunk_len == 0) {
break; }
28880 if (!read_content_with_length(strm, chunk_len,
nullptr, out)) {
28884 if (!line_reader.getline()) {
return false; }
28886 if (strcmp(line_reader.ptr(),
"\r\n") != 0) {
return false; }
28888 if (!line_reader.getline()) {
return false; }
28891 assert(chunk_len == 0);
28894 if (!line_reader.getline()) {
return false; }
28896 while (strcmp(line_reader.ptr(),
"\r\n") != 0) {
28897 if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) {
return false; }
28900 constexpr auto line_terminator_len = 2;
28901 auto end = line_reader.ptr() + line_reader.size() - line_terminator_len;
28903 parse_header(line_reader.ptr(), end,
28904 [&](
const std::string &key,
const std::string &val) {
28905 x.headers.emplace(key, val);
28908 if (!line_reader.getline()) {
return false; }
28914inline bool is_chunked_transfer_encoding(
const Headers &headers) {
28915 return compare_case_ignore(
28916 get_header_value(headers,
"Transfer-Encoding", 0,
""),
"chunked");
28919template <
typename T,
typename U>
28920bool prepare_content_receiver(T &x,
int &status,
28921 ContentReceiverWithProgress receiver,
28922 bool decompress, U callback) {
28924 std::string encoding = x.get_header_value(
"Content-Encoding");
28925 std::unique_ptr<decompressor> decompressor;
28927 if (encoding ==
"gzip" || encoding ==
"deflate") {
28928#ifdef CPPHTTPLIB_ZLIB_SUPPORT
28929 decompressor = detail::make_unique<gzip_decompressor>();
28931 status = StatusCode::UnsupportedMediaType_415;
28934 }
else if (encoding.find(
"br") != std::string::npos) {
28935#ifdef CPPHTTPLIB_BROTLI_SUPPORT
28936 decompressor = detail::make_unique<brotli_decompressor>();
28938 status = StatusCode::UnsupportedMediaType_415;
28943 if (decompressor) {
28944 if (decompressor->is_valid()) {
28945 ContentReceiverWithProgress out = [&](
const char *buf,
size_t n,
28946 uint64_t off, uint64_t len) {
28947 return decompressor->decompress(buf, n,
28948 [&](
const char *buf2,
size_t n2) {
28949 return receiver(buf2, n2, off, len);
28952 return callback(std::move(out));
28954 status = StatusCode::InternalServerError_500;
28960 ContentReceiverWithProgress out = [&](
const char *buf,
size_t n, uint64_t off,
28962 return receiver(buf, n, off, len);
28964 return callback(std::move(out));
28967template <
typename T>
28968bool read_content(Stream &strm, T &x,
size_t payload_max_length,
int &status,
28969 Progress progress, ContentReceiverWithProgress receiver,
28971 return prepare_content_receiver(
28972 x, status, std::move(receiver), decompress,
28973 [&](
const ContentReceiverWithProgress &out) {
28975 auto exceed_payload_max_length =
false;
28977 if (is_chunked_transfer_encoding(x.headers)) {
28978 ret = read_content_chunked(strm, x, out);
28979 }
else if (!has_header(x.headers,
"Content-Length")) {
28980 ret = read_content_without_length(strm, out);
28982 auto len = get_header_value_u64(x.headers,
"Content-Length", 0, 0);
28983 if (len > payload_max_length) {
28984 exceed_payload_max_length = true;
28985 skip_content_with_length(strm, len);
28987 }
else if (len > 0) {
28988 ret = read_content_with_length(strm, len, std::move(progress), out);
28993 status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413
28994 : StatusCode::BadRequest_400;
29000inline ssize_t write_headers(Stream &strm,
const Headers &headers) {
29001 ssize_t write_len = 0;
29002 for (
const auto &x : headers) {
29004 strm.write_format(
"%s: %s\r\n", x.first.c_str(), x.second.c_str());
29005 if (len < 0) {
return len; }
29008 auto len = strm.write(
"\r\n");
29009 if (len < 0) {
return len; }
29014inline bool write_data(Stream &strm,
const char *d,
size_t l) {
29016 while (offset < l) {
29017 auto length = strm.write(d + offset, l - offset);
29018 if (length < 0) {
return false; }
29019 offset +=
static_cast<size_t>(length);
29024template <
typename T>
29025inline bool write_content(Stream &strm,
const ContentProvider &content_provider,
29026 size_t offset,
size_t length, T is_shutting_down,
29028 size_t end_offset = offset + length;
29030 DataSink data_sink;
29032 data_sink.write = [&](
const char *d,
size_t l) ->
bool {
29034 if (strm.is_writable() && write_data(strm, d, l)) {
29043 data_sink.is_writable = [&]() ->
bool {
return strm.is_writable(); };
29045 while (offset < end_offset && !is_shutting_down()) {
29046 if (!strm.is_writable()) {
29047 error = Error::Write;
29049 }
else if (!content_provider(offset, end_offset - offset, data_sink)) {
29050 error = Error::Canceled;
29053 error = Error::Write;
29058 error = Error::Success;
29062template <
typename T>
29063inline bool write_content(Stream &strm,
const ContentProvider &content_provider,
29064 size_t offset,
size_t length,
29065 const T &is_shutting_down) {
29066 auto error = Error::Success;
29067 return write_content(strm, content_provider, offset, length, is_shutting_down,
29071template <
typename T>
29073write_content_without_length(Stream &strm,
29074 const ContentProvider &content_provider,
29075 const T &is_shutting_down) {
29077 auto data_available =
true;
29079 DataSink data_sink;
29081 data_sink.write = [&](
const char *d,
size_t l) ->
bool {
29084 if (!strm.is_writable() || !write_data(strm, d, l)) { ok =
false; }
29089 data_sink.is_writable = [&]() ->
bool {
return strm.is_writable(); };
29091 data_sink.done = [&](void) { data_available =
false; };
29093 while (data_available && !is_shutting_down()) {
29094 if (!strm.is_writable()) {
29096 }
else if (!content_provider(offset, 0, data_sink)) {
29105template <
typename T,
typename U>
29107write_content_chunked(Stream &strm,
const ContentProvider &content_provider,
29108 const T &is_shutting_down, U &compressor, Error &error) {
29110 auto data_available =
true;
29112 DataSink data_sink;
29114 data_sink.write = [&](
const char *d,
size_t l) ->
bool {
29116 data_available = l > 0;
29119 std::string payload;
29120 if (compressor.compress(d, l,
false,
29121 [&](
const char *data,
size_t data_len) {
29122 payload.append(data, data_len);
29125 if (!payload.empty()) {
29128 from_i_to_hex(payload.size()) +
"\r\n" + payload +
"\r\n";
29129 if (!strm.is_writable() ||
29130 !write_data(strm, chunk.data(), chunk.size())) {
29141 data_sink.is_writable = [&]() ->
bool {
return strm.is_writable(); };
29143 auto done_with_trailer = [&](
const Headers *trailer) {
29144 if (!ok) {
return; }
29146 data_available =
false;
29148 std::string payload;
29149 if (!compressor.compress(
nullptr, 0,
true,
29150 [&](
const char *data,
size_t data_len) {
29151 payload.append(data, data_len);
29158 if (!payload.empty()) {
29160 auto chunk = from_i_to_hex(payload.size()) +
"\r\n" + payload +
"\r\n";
29161 if (!strm.is_writable() ||
29162 !write_data(strm, chunk.data(), chunk.size())) {
29168 static const std::string done_marker(
"0\r\n");
29169 if (!write_data(strm, done_marker.data(), done_marker.size())) {
29175 for (
const auto &kv : *trailer) {
29176 std::string field_line = kv.first +
": " + kv.second +
"\r\n";
29177 if (!write_data(strm, field_line.data(), field_line.size())) {
29183 static const std::string crlf(
"\r\n");
29184 if (!write_data(strm, crlf.data(), crlf.size())) { ok =
false; }
29187 data_sink.done = [&](void) { done_with_trailer(
nullptr); };
29189 data_sink.done_with_trailer = [&](
const Headers &trailer) {
29190 done_with_trailer(&trailer);
29193 while (data_available && !is_shutting_down()) {
29194 if (!strm.is_writable()) {
29195 error = Error::Write;
29197 }
else if (!content_provider(offset, 0, data_sink)) {
29198 error = Error::Canceled;
29201 error = Error::Write;
29206 error = Error::Success;
29210template <
typename T,
typename U>
29211inline bool write_content_chunked(Stream &strm,
29212 const ContentProvider &content_provider,
29213 const T &is_shutting_down, U &compressor) {
29214 auto error = Error::Success;
29215 return write_content_chunked(strm, content_provider, is_shutting_down,
29216 compressor, error);
29219template <
typename T>
29220inline bool redirect(T &cli, Request &req, Response &res,
29221 const std::string &path,
const std::string &location,
29223 Request new_req = req;
29224 new_req.path = path;
29225 new_req.redirect_count_ -= 1;
29227 if (res.status == StatusCode::SeeOther_303 &&
29228 (req.method !=
"GET" && req.method !=
"HEAD")) {
29229 new_req.method =
"GET";
29230 new_req.body.clear();
29231 new_req.headers.clear();
29236 auto ret = cli.send(new_req, new_res, error);
29241 if (res.location.empty()) { res.location = location; }
29246inline std::string params_to_query_str(
const Params ¶ms) {
29249 for (
auto it = params.begin(); it != params.end(); ++it) {
29250 if (it != params.begin()) { query +=
"&"; }
29251 query += it->first;
29253 query += encode_query_param(it->second);
29258inline void parse_query_text(
const char *data, std::size_t size,
29260 std::set<std::string> cache;
29261 split(data, data + size,
'&', [&](
const char *b,
const char *e) {
29262 std::string kv(b, e);
29263 if (cache.find(kv) != cache.end()) {
return; }
29264 cache.insert(std::move(kv));
29268 divide(b,
static_cast<std::size_t
>(e - b),
'=',
29269 [&](
const char *lhs_data, std::size_t lhs_size,
const char *rhs_data,
29270 std::size_t rhs_size) {
29271 key.assign(lhs_data, lhs_size);
29272 val.assign(rhs_data, rhs_size);
29275 if (!
key.empty()) {
29276 params.emplace(decode_url(key,
true), decode_url(val,
true));
29281inline void parse_query_text(
const std::string &s, Params ¶ms) {
29282 parse_query_text(s.data(), s.size(), params);
29285inline bool parse_multipart_boundary(
const std::string &content_type,
29286 std::string &boundary) {
29287 auto boundary_keyword =
"boundary=";
29288 auto pos = content_type.find(boundary_keyword);
29289 if (pos == std::string::npos) {
return false; }
29290 auto end = content_type.find(
';', pos);
29291 auto beg = pos + strlen(boundary_keyword);
29292 boundary = trim_double_quotes_copy(content_type.substr(beg, end - beg));
29293 return !boundary.empty();
29296inline void parse_disposition_params(
const std::string &s, Params ¶ms) {
29297 std::set<std::string> cache;
29298 split(s.data(), s.data() + s.size(),
';', [&](
const char *b,
const char *e) {
29299 std::string kv(b, e);
29300 if (cache.find(kv) != cache.end()) { return; }
29305 split(b, e,
'=', [&](
const char *b2,
const char *e2) {
29307 key.assign(b2, e2);
29309 val.assign(b2, e2);
29313 if (!
key.empty()) {
29314 params.emplace(trim_double_quotes_copy((key)),
29315 trim_double_quotes_copy((val)));
29320#ifdef CPPHTTPLIB_NO_EXCEPTIONS
29321inline bool parse_range_header(
const std::string &s, Ranges &ranges) {
29323inline bool parse_range_header(
const std::string &s, Ranges &ranges)
try {
29325 auto is_valid = [](
const std::string &str) {
29326 return std::all_of(str.cbegin(), str.cend(),
29327 [](
unsigned char c) { return std::isdigit(c); });
29330 if (s.size() > 7 && s.compare(0, 6,
"bytes=") == 0) {
29331 const auto pos =
static_cast<size_t>(6);
29332 const auto len =
static_cast<size_t>(s.size() - 6);
29333 auto all_valid_ranges =
true;
29334 split(&s[pos], &s[pos + len],
',', [&](
const char *b,
const char *e) {
29335 if (!all_valid_ranges) {
return; }
29337 const auto it = std::find(b, e,
'-');
29339 all_valid_ranges =
false;
29343 const auto lhs = std::string(b, it);
29344 const auto rhs = std::string(it + 1, e);
29345 if (!is_valid(lhs) || !is_valid(rhs)) {
29346 all_valid_ranges =
false;
29351 static_cast<ssize_t
>(lhs.empty() ? -1 : std::stoll(lhs));
29353 static_cast<ssize_t
>(rhs.empty() ? -1 : std::stoll(rhs));
29354 if ((first == -1 && last == -1) ||
29355 (first != -1 && last != -1 && first > last)) {
29356 all_valid_ranges =
false;
29360 ranges.emplace_back(first, last);
29362 return all_valid_ranges && !ranges.empty();
29365#ifdef CPPHTTPLIB_NO_EXCEPTIONS
29368}
catch (...) {
return false; }
29375 void set_boundary(std::string &&boundary) {
29376 boundary_ = boundary;
29377 dash_boundary_crlf_ = dash_ + boundary_ + crlf_;
29378 crlf_dash_boundary_ = crlf_ + dash_ + boundary_;
29381 bool is_valid()
const {
return is_valid_; }
29383 bool parse(
const char *buf,
size_t n,
const ContentReceiver &content_callback,
29384 const MultipartContentHeader &header_callback) {
29386 buf_append(buf, n);
29388 while (buf_size() > 0) {
29391 buf_erase(buf_find(dash_boundary_crlf_));
29392 if (dash_boundary_crlf_.size() > buf_size()) {
return true; }
29393 if (!buf_start_with(dash_boundary_crlf_)) {
return false; }
29394 buf_erase(dash_boundary_crlf_.size());
29404 auto pos = buf_find(crlf_);
29405 if (pos > CPPHTTPLIB_HEADER_MAX_LENGTH) {
return false; }
29406 while (pos < buf_size()) {
29409 if (!header_callback(file_)) {
29413 buf_erase(crlf_.size());
29418 const auto header = buf_head(pos);
29420 if (!parse_header(header.data(), header.data() + header.size(),
29421 [&](
const std::string &,
const std::string &) {})) {
29426 static const std::string header_content_type =
"Content-Type:";
29428 if (start_with_case_ignore(header, header_content_type)) {
29429 file_.content_type =
29430 trim_copy(header.substr(header_content_type.size()));
29432 static const std::regex re_content_disposition(
29433 R
"~(^Content-Disposition:\s*form-data;\s*(.*)$)~",
29434 std::regex_constants::icase);
29437 if (std::regex_match(header, m, re_content_disposition)) {
29439 parse_disposition_params(m[1], params);
29441 auto it = params.find(
"name");
29442 if (it != params.end()) {
29443 file_.name = it->second;
29449 it = params.find(
"filename");
29450 if (it != params.end()) { file_.filename = it->second; }
29452 it = params.find(
"filename*");
29453 if (it != params.end()) {
29455 static const std::regex re_rfc5987_encoding(
29456 R
"~(^UTF-8''(.+?)$)~", std::regex_constants::icase);
29459 if (std::regex_match(it->second, m2, re_rfc5987_encoding)) {
29460 file_.filename = decode_url(m2[1],
false);
29468 buf_erase(pos + crlf_.size());
29469 pos = buf_find(crlf_);
29471 if (state_ != 3) {
return true; }
29475 if (crlf_dash_boundary_.size() > buf_size()) {
return true; }
29476 auto pos = buf_find(crlf_dash_boundary_);
29477 if (pos < buf_size()) {
29478 if (!content_callback(buf_data(), pos)) {
29482 buf_erase(pos + crlf_dash_boundary_.size());
29485 auto len = buf_size() - crlf_dash_boundary_.size();
29487 if (!content_callback(buf_data(), len)) {
29498 if (crlf_.size() > buf_size()) {
return true; }
29499 if (buf_start_with(crlf_)) {
29500 buf_erase(crlf_.size());
29503 if (dash_.size() > buf_size()) {
return true; }
29504 if (buf_start_with(dash_)) {
29505 buf_erase(dash_.size());
29507 buf_erase(buf_size());
29521 void clear_file_info() {
29522 file_.name.clear();
29523 file_.filename.clear();
29524 file_.content_type.clear();
29527 bool start_with_case_ignore(
const std::string &a,
29528 const std::string &b)
const {
29529 if (a.size() < b.size()) {
return false; }
29530 for (
size_t i = 0; i < b.size(); i++) {
29531 if (::tolower(a[i]) != ::tolower(b[i])) {
return false; }
29536 const std::string dash_ =
"--";
29537 const std::string crlf_ =
"\r\n";
29538 std::string boundary_;
29539 std::string dash_boundary_crlf_;
29540 std::string crlf_dash_boundary_;
29543 bool is_valid_ =
false;
29547 bool start_with(
const std::string &a,
size_t spos,
size_t epos,
29548 const std::string &b)
const {
29549 if (epos - spos < b.size()) {
return false; }
29550 for (
size_t i = 0; i < b.size(); i++) {
29551 if (a[i + spos] != b[i]) {
return false; }
29556 size_t buf_size()
const {
return buf_epos_ - buf_spos_; }
29558 const char *buf_data()
const {
return &buf_[buf_spos_]; }
29560 std::string buf_head(
size_t l)
const {
return buf_.substr(buf_spos_, l); }
29562 bool buf_start_with(
const std::string &s)
const {
29563 return start_with(buf_, buf_spos_, buf_epos_, s);
29566 size_t buf_find(
const std::string &s)
const {
29567 auto c = s.front();
29569 size_t off = buf_spos_;
29570 while (off < buf_epos_) {
29573 if (pos == buf_epos_) {
return buf_size(); }
29574 if (buf_[pos] == c) {
break; }
29578 auto remaining_size = buf_epos_ - pos;
29579 if (s.size() > remaining_size) {
return buf_size(); }
29581 if (start_with(buf_, pos, buf_epos_, s)) {
return pos - buf_spos_; }
29589 void buf_append(
const char *data,
size_t n) {
29590 auto remaining_size = buf_size();
29591 if (remaining_size > 0 && buf_spos_ > 0) {
29592 for (
size_t i = 0; i < remaining_size; i++) {
29593 buf_[i] = buf_[buf_spos_ + i];
29597 buf_epos_ = remaining_size;
29599 if (remaining_size + n > buf_.size()) { buf_.resize(remaining_size + n); }
29601 for (
size_t i = 0; i < n; i++) {
29602 buf_[buf_epos_ + i] = data[i];
29607 void buf_erase(
size_t size) { buf_spos_ += size; }
29610 size_t buf_spos_ = 0;
29611 size_t buf_epos_ = 0;
29614inline std::string to_lower(
const char *beg,
const char *end) {
29617 while (it != end) {
29618 out +=
static_cast<char>(::tolower(*it));
29624inline std::string random_string(
size_t length) {
29625 static const char data[] =
29626 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
29631 static std::random_device seed_gen;
29634 static std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(),
29637 static std::mt19937 engine(seed_sequence);
29639 std::string result;
29640 for (
size_t i = 0; i < length; i++) {
29641 result += data[engine() % (
sizeof(data) - 1)];
29646inline std::string make_multipart_data_boundary() {
29647 return "--cpp-httplib-multipart-data-" + detail::random_string(16);
29650inline bool is_multipart_boundary_chars_valid(
const std::string &boundary) {
29652 for (
size_t i = 0; i < boundary.size(); i++) {
29653 auto c = boundary[i];
29654 if (!std::isalnum(c) && c !=
'-' && c !=
'_') {
29662template <
typename T>
29664serialize_multipart_formdata_item_begin(
const T &item,
29665 const std::string &boundary) {
29666 std::string body =
"--" + boundary +
"\r\n";
29667 body +=
"Content-Disposition: form-data; name=\"" + item.name +
"\"";
29668 if (!item.filename.empty()) {
29669 body +=
"; filename=\"" + item.filename +
"\"";
29672 if (!item.content_type.empty()) {
29673 body +=
"Content-Type: " + item.content_type +
"\r\n";
29680inline std::string serialize_multipart_formdata_item_end() {
return "\r\n"; }
29683serialize_multipart_formdata_finish(
const std::string &boundary) {
29684 return "--" + boundary +
"--\r\n";
29688serialize_multipart_formdata_get_content_type(
const std::string &boundary) {
29689 return "multipart/form-data; boundary=" + boundary;
29693serialize_multipart_formdata(
const MultipartFormDataItems &items,
29694 const std::string &boundary,
bool finish =
true) {
29697 for (
const auto &item : items) {
29698 body += serialize_multipart_formdata_item_begin(item, boundary);
29699 body += item.content + serialize_multipart_formdata_item_end();
29702 if (finish) { body += serialize_multipart_formdata_finish(boundary); }
29707inline bool range_error(Request &req, Response &res) {
29708 if (!req.ranges.empty() && 200 <= res.status && res.status < 300) {
29709 ssize_t contant_len =
static_cast<ssize_t
>(
29710 res.content_length_ ? res.content_length_ : res.body.size());
29712 ssize_t prev_first_pos = -1;
29713 ssize_t prev_last_pos = -1;
29714 size_t overwrapping_count = 0;
29721 if (req.ranges.size() > CPPHTTPLIB_RANGE_MAX_COUNT) {
return true; }
29723 for (
auto &r : req.ranges) {
29724 auto &first_pos = r.first;
29725 auto &last_pos = r.second;
29727 if (first_pos == -1 && last_pos == -1) {
29729 last_pos = contant_len;
29732 if (first_pos == -1) {
29733 first_pos = contant_len - last_pos;
29734 last_pos = contant_len - 1;
29737 if (last_pos == -1) { last_pos = contant_len - 1; }
29740 if (!(0 <= first_pos && first_pos <= last_pos &&
29741 last_pos <= contant_len - 1)) {
29746 if (first_pos <= prev_first_pos) {
return true; }
29749 if (first_pos <= prev_last_pos) {
29750 overwrapping_count++;
29751 if (overwrapping_count > 2) {
return true; }
29754 prev_first_pos = (std::max)(prev_first_pos, first_pos);
29755 prev_last_pos = (std::max)(prev_last_pos, last_pos);
29762inline std::pair<size_t, size_t>
29763get_range_offset_and_length(Range r,
size_t content_length) {
29764 assert(r.first != -1 && r.second != -1);
29765 assert(0 <= r.first && r.first <
static_cast<ssize_t
>(content_length));
29766 assert(r.first <= r.second &&
29767 r.second <
static_cast<ssize_t
>(content_length));
29769 return std::make_pair(r.first,
static_cast<size_t>(r.second - r.first) + 1);
29772inline std::string make_content_range_header_field(
29773 const std::pair<size_t, size_t> &offset_and_length,
size_t content_length) {
29774 auto st = offset_and_length.first;
29775 auto ed = st + offset_and_length.second - 1;
29777 std::string field =
"bytes ";
29778 field += std::to_string(st);
29780 field += std::to_string(ed);
29782 field += std::to_string(content_length);
29786template <
typename SToken,
typename CToken,
typename Content>
29787bool process_multipart_ranges_data(
const Request &req,
29788 const std::string &boundary,
29789 const std::string &content_type,
29790 size_t content_length, SToken stoken,
29791 CToken ctoken, Content content) {
29792 for (
size_t i = 0; i < req.ranges.size(); i++) {
29796 if (!content_type.empty()) {
29797 ctoken(
"Content-Type: ");
29798 stoken(content_type);
29802 auto offset_and_length =
29803 get_range_offset_and_length(req.ranges[i], content_length);
29805 ctoken(
"Content-Range: ");
29806 stoken(make_content_range_header_field(offset_and_length, content_length));
29810 if (!content(offset_and_length.first, offset_and_length.second)) {
29823inline void make_multipart_ranges_data(
const Request &req, Response &res,
29824 const std::string &boundary,
29825 const std::string &content_type,
29826 size_t content_length,
29827 std::string &data) {
29828 process_multipart_ranges_data(
29829 req, boundary, content_type, content_length,
29830 [&](
const std::string &token) { data += token; },
29831 [&](
const std::string &token) { data += token; },
29832 [&](
size_t offset,
size_t length) {
29833 assert(offset + length <= content_length);
29834 data += res.body.substr(offset, length);
29839inline size_t get_multipart_ranges_data_length(
const Request &req,
29840 const std::string &boundary,
29841 const std::string &content_type,
29842 size_t content_length) {
29843 size_t data_length = 0;
29845 process_multipart_ranges_data(
29846 req, boundary, content_type, content_length,
29847 [&](
const std::string &token) { data_length += token.size(); },
29848 [&](
const std::string &token) { data_length += token.size(); },
29849 [&](
size_t ,
size_t length) {
29850 data_length += length;
29854 return data_length;
29857template <
typename T>
29859write_multipart_ranges_data(Stream &strm,
const Request &req, Response &res,
29860 const std::string &boundary,
29861 const std::string &content_type,
29862 size_t content_length,
const T &is_shutting_down) {
29863 return process_multipart_ranges_data(
29864 req, boundary, content_type, content_length,
29865 [&](
const std::string &token) { strm.write(token); },
29866 [&](
const std::string &token) { strm.write(token); },
29867 [&](
size_t offset,
size_t length) {
29868 return write_content(strm, res.content_provider_, offset, length,
29873inline bool expect_content(
const Request &req) {
29874 if (req.method ==
"POST" || req.method ==
"PUT" || req.method ==
"PATCH" ||
29875 req.method ==
"PRI" || req.method ==
"DELETE") {
29882inline bool has_crlf(
const std::string &s) {
29883 auto p = s.c_str();
29885 if (*p ==
'\r' || *p ==
'\n') {
return true; }
29891#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
29892inline std::string message_digest(
const std::string &s,
const EVP_MD *algo) {
29893 auto context = std::unique_ptr<EVP_MD_CTX, decltype(&EVP_MD_CTX_free)>(
29894 EVP_MD_CTX_new(), EVP_MD_CTX_free);
29896 unsigned int hash_length = 0;
29897 unsigned char hash[EVP_MAX_MD_SIZE];
29899 EVP_DigestInit_ex(context.get(), algo,
nullptr);
29900 EVP_DigestUpdate(context.get(), s.c_str(), s.size());
29901 EVP_DigestFinal_ex(context.get(), hash, &hash_length);
29903 std::stringstream ss;
29904 for (
auto i = 0u; i < hash_length; ++i) {
29905 ss << std::hex << std::setw(2) << std::setfill(
'0')
29906 <<
static_cast<unsigned int>(
hash[i]);
29912inline std::string MD5(
const std::string &s) {
29913 return message_digest(s, EVP_md5());
29916inline std::string SHA_256(
const std::string &s) {
29917 return message_digest(s, EVP_sha256());
29920inline std::string SHA_512(
const std::string &s) {
29921 return message_digest(s, EVP_sha512());
29925#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
29929inline bool load_system_certs_on_windows(X509_STORE *store) {
29930 auto hStore = CertOpenSystemStoreW((HCRYPTPROV_LEGACY)NULL, L
"ROOT");
29931 if (!hStore) {
return false; }
29933 auto result =
false;
29934 PCCERT_CONTEXT pContext = NULL;
29935 while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) !=
29937 auto encoded_cert =
29938 static_cast<const unsigned char *
>(pContext->pbCertEncoded);
29940 auto x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded);
29942 X509_STORE_add_cert(store, x509);
29948 CertFreeCertificateContext(pContext);
29949 CertCloseStore(hStore, 0);
29953#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
29955template <
typename T>
29957 std::unique_ptr<typename std::remove_pointer<T>::type, void (*)(CFTypeRef)>;
29959inline void cf_object_ptr_deleter(CFTypeRef obj) {
29960 if (obj) { CFRelease(obj); }
29963inline bool retrieve_certs_from_keychain(CFObjectPtr<CFArrayRef> &certs) {
29964 CFStringRef keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef};
29965 CFTypeRef values[] = {kSecClassCertificate, kSecMatchLimitAll,
29968 CFObjectPtr<CFDictionaryRef> query(
29969 CFDictionaryCreate(
nullptr,
reinterpret_cast<const void **
>(keys), values,
29970 sizeof(keys) /
sizeof(keys[0]),
29971 &kCFTypeDictionaryKeyCallBacks,
29972 &kCFTypeDictionaryValueCallBacks),
29973 cf_object_ptr_deleter);
29975 if (!query) {
return false; }
29977 CFTypeRef security_items =
nullptr;
29978 if (SecItemCopyMatching(query.get(), &security_items) != errSecSuccess ||
29979 CFArrayGetTypeID() != CFGetTypeID(security_items)) {
29983 certs.reset(
reinterpret_cast<CFArrayRef
>(security_items));
29987inline bool retrieve_root_certs_from_keychain(CFObjectPtr<CFArrayRef> &certs) {
29988 CFArrayRef root_security_items =
nullptr;
29989 if (SecTrustCopyAnchorCertificates(&root_security_items) != errSecSuccess) {
29993 certs.reset(root_security_items);
29997inline bool add_certs_to_x509_store(CFArrayRef certs, X509_STORE *store) {
29998 auto result =
false;
29999 for (
auto i = 0; i < CFArrayGetCount(certs); ++i) {
30000 const auto cert =
reinterpret_cast<const __SecCertificate *
>(
30001 CFArrayGetValueAtIndex(certs, i));
30003 if (SecCertificateGetTypeID() != CFGetTypeID(cert)) {
continue; }
30005 CFDataRef cert_data =
nullptr;
30006 if (SecItemExport(cert, kSecFormatX509Cert, 0,
nullptr, &cert_data) !=
30011 CFObjectPtr<CFDataRef> cert_data_ptr(cert_data, cf_object_ptr_deleter);
30013 auto encoded_cert =
static_cast<const unsigned char *
>(
30014 CFDataGetBytePtr(cert_data_ptr.get()));
30017 d2i_X509(NULL, &encoded_cert, CFDataGetLength(cert_data_ptr.get()));
30020 X509_STORE_add_cert(store, x509);
30029inline bool load_system_certs_on_macos(X509_STORE *store) {
30030 auto result =
false;
30031 CFObjectPtr<CFArrayRef> certs(
nullptr, cf_object_ptr_deleter);
30032 if (retrieve_certs_from_keychain(certs) && certs) {
30033 result = add_certs_to_x509_store(certs.get(), store);
30036 if (retrieve_root_certs_from_keychain(certs) && certs) {
30037 result = add_certs_to_x509_store(certs.get(), store) || result;
30051 if (WSAStartup(0x0002, &wsaData) == 0) is_valid_ =
true;
30055 if (is_valid_) WSACleanup();
30058 bool is_valid_ =
false;
30061static WSInit wsinit_;
30064#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
30065inline std::pair<std::string, std::string> make_digest_authentication_header(
30066 const Request &req,
const std::map<std::string, std::string> &auth,
30067 size_t cnonce_count,
const std::string &cnonce,
const std::string &username,
30068 const std::string &password,
bool is_proxy =
false) {
30071 std::stringstream ss;
30072 ss << std::setfill(
'0') << std::setw(8) << std::hex << cnonce_count;
30077 if (auth.find(
"qop") != auth.end()) {
30078 qop = auth.at(
"qop");
30079 if (qop.find(
"auth-int") != std::string::npos) {
30081 }
else if (qop.find(
"auth") != std::string::npos) {
30088 std::string algo =
"MD5";
30089 if (auth.find(
"algorithm") != auth.end()) { algo = auth.at(
"algorithm"); }
30091 std::string response;
30093 auto H = algo ==
"SHA-256" ? detail::SHA_256
30094 : algo ==
"SHA-512" ? detail::SHA_512
30097 auto A1 = username +
":" + auth.at(
"realm") +
":" + password;
30099 auto A2 = req.method +
":" + req.path;
30100 if (qop ==
"auth-int") { A2 +=
":" + H(req.body); }
30103 response = H(H(A1) +
":" + auth.at(
"nonce") +
":" + H(A2));
30105 response = H(H(A1) +
":" + auth.at(
"nonce") +
":" + nc +
":" + cnonce +
30106 ":" + qop +
":" + H(A2));
30110 auto opaque = (auth.find(
"opaque") != auth.end()) ? auth.at(
"opaque") :
"";
30112 auto field =
"Digest username=\"" + username +
"\", realm=\"" +
30113 auth.at(
"realm") +
"\", nonce=\"" + auth.at(
"nonce") +
30114 "\", uri=\"" + req.path +
"\", algorithm=" + algo +
30115 (qop.empty() ?
", response=\""
30116 :
", qop=" + qop +
", nc=" + nc +
", cnonce=\"" +
30117 cnonce +
"\", response=\"") +
30119 (opaque.empty() ?
"" :
", opaque=\"" + opaque +
"\"");
30121 auto key = is_proxy ?
"Proxy-Authorization" :
"Authorization";
30122 return std::make_pair(key, field);
30126inline bool parse_www_authenticate(
const Response &res,
30127 std::map<std::string, std::string> &auth,
30129 auto auth_key = is_proxy ?
"Proxy-Authenticate" :
"WWW-Authenticate";
30130 if (res.has_header(auth_key)) {
30131 static auto re = std::regex(R
"~((?:(?:,\s*)?(.+?)=(?:"(.*?)"|([^,]*))))~");
30132 auto s = res.get_header_value(auth_key);
30133 auto pos = s.find(
' ');
30134 if (pos != std::string::npos) {
30135 auto type = s.substr(0, pos);
30136 if (type ==
"Basic") {
30138 }
else if (type ==
"Digest") {
30139 s = s.substr(pos + 1);
30140 auto beg = std::sregex_iterator(s.begin(), s.end(), re);
30141 for (
auto i = beg; i != std::sregex_iterator(); ++i) {
30142 const auto &m = *i;
30143 auto key = s.substr(
static_cast<size_t>(m.position(1)),
30144 static_cast<size_t>(m.length(1)));
30145 auto val = m.length(2) > 0
30146 ? s.substr(
static_cast<size_t>(m.position(2)),
30147 static_cast<size_t>(m.length(2)))
30148 : s.substr(
static_cast<size_t>(m.position(3)),
30149 static_cast<size_t>(m.length(3)));
30162 ContentProviderWithoutLength &&content_provider)
30163 : content_provider_(content_provider) {}
30165 bool operator()(
size_t offset,
size_t,
DataSink &sink) {
30166 return content_provider_(offset, sink);
30170 ContentProviderWithoutLength content_provider_;
30175inline std::string hosted_at(
const std::string &hostname) {
30176 std::vector<std::string> addrs;
30177 hosted_at(hostname, addrs);
30178 if (addrs.empty()) {
return std::string(); }
30182inline void hosted_at(
const std::string &hostname,
30183 std::vector<std::string> &addrs) {
30184 struct addrinfo hints;
30185 struct addrinfo *result;
30187 memset(&hints, 0,
sizeof(
struct addrinfo));
30188 hints.ai_family = AF_UNSPEC;
30189 hints.ai_socktype = SOCK_STREAM;
30190 hints.ai_protocol = 0;
30192 if (getaddrinfo(hostname.c_str(),
nullptr, &hints, &result)) {
30193#if defined __linux__ && !defined __ANDROID__
30199 for (
auto rp = result; rp; rp = rp->ai_next) {
30201 *
reinterpret_cast<struct sockaddr_storage *
>(rp->ai_addr);
30204 if (detail::get_ip_and_port(addr,
sizeof(
struct sockaddr_storage), ip,
30206 addrs.push_back(ip);
30210 freeaddrinfo(result);
30213inline std::string append_query_params(
const std::string &path,
30214 const Params ¶ms) {
30215 std::string path_with_query = path;
30216 const static std::regex re(
"[^?]+\\?.*");
30217 auto delm = std::regex_match(path, re) ?
'&' :
'?';
30218 path_with_query += delm + detail::params_to_query_str(params);
30219 return path_with_query;
30223inline std::pair<std::string, std::string>
30224make_range_header(
const Ranges &ranges) {
30225 std::string field =
"bytes=";
30227 for (
const auto &r : ranges) {
30228 if (i != 0) { field +=
", "; }
30229 if (r.first != -1) { field += std::to_string(r.first); }
30231 if (r.second != -1) { field += std::to_string(r.second); }
30234 return std::make_pair(
"Range", std::move(field));
30237inline std::pair<std::string, std::string>
30238make_basic_authentication_header(
const std::string &username,
30239 const std::string &password,
bool is_proxy) {
30240 auto field =
"Basic " + detail::base64_encode(username +
":" + password);
30241 auto key = is_proxy ?
"Proxy-Authorization" :
"Authorization";
30242 return std::make_pair(key, std::move(field));
30245inline std::pair<std::string, std::string>
30246make_bearer_token_authentication_header(
const std::string &token,
30247 bool is_proxy =
false) {
30248 auto field =
"Bearer " + token;
30249 auto key = is_proxy ?
"Proxy-Authorization" :
"Authorization";
30250 return std::make_pair(key, std::move(field));
30254inline bool Request::has_header(
const std::string &key)
const {
30255 return detail::has_header(headers, key);
30258inline std::string Request::get_header_value(
const std::string &key,
30260 return detail::get_header_value(headers, key,
id,
"");
30263inline size_t Request::get_header_value_count(
const std::string &key)
const {
30264 auto r = headers.equal_range(key);
30265 return static_cast<size_t>(std::distance(r.first, r.second));
30268inline void Request::set_header(
const std::string &key,
30269 const std::string &val) {
30270 if (!detail::has_crlf(key) && !detail::has_crlf(val)) {
30271 headers.emplace(key, val);
30275inline bool Request::has_param(
const std::string &key)
const {
30276 return params.find(key) != params.end();
30279inline std::string Request::get_param_value(
const std::string &key,
30281 auto rng = params.equal_range(key);
30282 auto it = rng.first;
30283 std::advance(it,
static_cast<ssize_t
>(
id));
30284 if (it != rng.second) {
return it->second; }
30285 return std::string();
30288inline size_t Request::get_param_value_count(
const std::string &key)
const {
30289 auto r = params.equal_range(key);
30290 return static_cast<size_t>(std::distance(r.first, r.second));
30293inline bool Request::is_multipart_form_data()
const {
30294 const auto &content_type = get_header_value(
"Content-Type");
30295 return !content_type.rfind(
"multipart/form-data", 0);
30298inline bool Request::has_file(
const std::string &key)
const {
30299 return files.find(key) != files.end();
30302inline MultipartFormData Request::get_file_value(
const std::string &key)
const {
30303 auto it = files.find(key);
30304 if (it != files.end()) {
return it->second; }
30305 return MultipartFormData();
30308inline std::vector<MultipartFormData>
30309Request::get_file_values(
const std::string &key)
const {
30310 std::vector<MultipartFormData> values;
30311 auto rng = files.equal_range(key);
30312 for (
auto it = rng.first; it != rng.second; it++) {
30313 values.push_back(it->second);
30319inline bool Response::has_header(
const std::string &key)
const {
30320 return headers.find(key) != headers.end();
30323inline std::string Response::get_header_value(
const std::string &key,
30325 return detail::get_header_value(headers, key,
id,
"");
30328inline size_t Response::get_header_value_count(
const std::string &key)
const {
30329 auto r = headers.equal_range(key);
30330 return static_cast<size_t>(std::distance(r.first, r.second));
30333inline void Response::set_header(
const std::string &key,
30334 const std::string &val) {
30335 if (!detail::has_crlf(key) && !detail::has_crlf(val)) {
30336 headers.emplace(key, val);
30340inline void Response::set_redirect(
const std::string &url,
int stat) {
30341 if (!detail::has_crlf(url)) {
30342 set_header(
"Location", url);
30343 if (300 <= stat && stat < 400) {
30344 this->status = stat;
30346 this->status = StatusCode::Found_302;
30351inline void Response::set_content(
const char *s,
size_t n,
30352 const std::string &content_type) {
30355 auto rng = headers.equal_range(
"Content-Type");
30356 headers.erase(rng.first, rng.second);
30357 set_header(
"Content-Type", content_type);
30360inline void Response::set_content(
const std::string &s,
30361 const std::string &content_type) {
30362 set_content(s.data(), s.size(), content_type);
30365inline void Response::set_content(std::string &&s,
30366 const std::string &content_type) {
30367 body = std::move(s);
30369 auto rng = headers.equal_range(
"Content-Type");
30370 headers.erase(rng.first, rng.second);
30371 set_header(
"Content-Type", content_type);
30374inline void Response::set_content_provider(
30375 size_t in_length,
const std::string &content_type, ContentProvider provider,
30376 ContentProviderResourceReleaser resource_releaser) {
30377 set_header(
"Content-Type", content_type);
30378 content_length_ = in_length;
30379 if (in_length > 0) { content_provider_ = std::move(provider); }
30380 content_provider_resource_releaser_ = std::move(resource_releaser);
30381 is_chunked_content_provider_ =
false;
30384inline void Response::set_content_provider(
30385 const std::string &content_type, ContentProviderWithoutLength provider,
30386 ContentProviderResourceReleaser resource_releaser) {
30387 set_header(
"Content-Type", content_type);
30388 content_length_ = 0;
30389 content_provider_ = detail::ContentProviderAdapter(std::move(provider));
30390 content_provider_resource_releaser_ = std::move(resource_releaser);
30391 is_chunked_content_provider_ =
false;
30394inline void Response::set_chunked_content_provider(
30395 const std::string &content_type, ContentProviderWithoutLength provider,
30396 ContentProviderResourceReleaser resource_releaser) {
30397 set_header(
"Content-Type", content_type);
30398 content_length_ = 0;
30399 content_provider_ = detail::ContentProviderAdapter(std::move(provider));
30400 content_provider_resource_releaser_ = std::move(resource_releaser);
30401 is_chunked_content_provider_ =
true;
30405inline bool Result::has_request_header(
const std::string &key)
const {
30406 return request_headers_.find(key) != request_headers_.end();
30409inline std::string Result::get_request_header_value(
const std::string &key,
30411 return detail::get_header_value(request_headers_, key,
id,
"");
30415Result::get_request_header_value_count(
const std::string &key)
const {
30416 auto r = request_headers_.equal_range(key);
30417 return static_cast<size_t>(std::distance(r.first, r.second));
30421inline ssize_t Stream::write(
const char *ptr) {
30422 return write(ptr, strlen(ptr));
30425inline ssize_t Stream::write(
const std::string &s) {
30426 return write(s.data(), s.size());
30432inline SocketStream::SocketStream(socket_t sock, time_t read_timeout_sec,
30433 time_t read_timeout_usec,
30434 time_t write_timeout_sec,
30435 time_t write_timeout_usec)
30436 : sock_(sock), read_timeout_sec_(read_timeout_sec),
30437 read_timeout_usec_(read_timeout_usec),
30438 write_timeout_sec_(write_timeout_sec),
30439 write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {}
30441inline SocketStream::~SocketStream() =
default;
30443inline bool SocketStream::is_readable()
const {
30444 return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
30447inline bool SocketStream::is_writable()
const {
30448 return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
30449 is_socket_alive(sock_);
30452inline ssize_t SocketStream::read(
char *ptr,
size_t size) {
30455 (std::min)(size,
static_cast<size_t>((std::numeric_limits<int>::max)()));
30457 size = (std::min)(size,
30458 static_cast<size_t>((std::numeric_limits<ssize_t>::max)()));
30461 if (read_buff_off_ < read_buff_content_size_) {
30462 auto remaining_size = read_buff_content_size_ - read_buff_off_;
30463 if (size <= remaining_size) {
30464 memcpy(ptr, read_buff_.data() + read_buff_off_, size);
30465 read_buff_off_ += size;
30466 return static_cast<ssize_t
>(size);
30468 memcpy(ptr, read_buff_.data() + read_buff_off_, remaining_size);
30469 read_buff_off_ += remaining_size;
30470 return static_cast<ssize_t
>(remaining_size);
30474 if (!is_readable()) {
return -1; }
30476 read_buff_off_ = 0;
30477 read_buff_content_size_ = 0;
30479 if (size < read_buff_size_) {
30480 auto n = read_socket(sock_, read_buff_.data(), read_buff_size_,
30481 CPPHTTPLIB_RECV_FLAGS);
30484 }
else if (n <=
static_cast<ssize_t
>(size)) {
30485 memcpy(ptr, read_buff_.data(),
static_cast<size_t>(n));
30488 memcpy(ptr, read_buff_.data(), size);
30489 read_buff_off_ = size;
30490 read_buff_content_size_ =
static_cast<size_t>(n);
30491 return static_cast<ssize_t
>(size);
30494 return read_socket(sock_, ptr, size, CPPHTTPLIB_RECV_FLAGS);
30498inline ssize_t SocketStream::write(
const char *ptr,
size_t size) {
30499 if (!is_writable()) {
return -1; }
30501#if defined(_WIN32) && !defined(_WIN64)
30503 (std::min)(size,
static_cast<size_t>((std::numeric_limits<int>::max)()));
30506 return send_socket(sock_, ptr, size, CPPHTTPLIB_SEND_FLAGS);
30509inline void SocketStream::get_remote_ip_and_port(std::string &ip,
30511 return detail::get_remote_ip_and_port(sock_, ip, port);
30514inline void SocketStream::get_local_ip_and_port(std::string &ip,
30516 return detail::get_local_ip_and_port(sock_, ip, port);
30519inline socket_t SocketStream::socket()
const {
return sock_; }
30522inline bool BufferStream::is_readable()
const {
return true; }
30524inline bool BufferStream::is_writable()
const {
return true; }
30526inline ssize_t BufferStream::read(
char *ptr,
size_t size) {
30527#if defined(_MSC_VER) && _MSC_VER < 1910
30528 auto len_read = buffer._Copy_s(ptr, size, size, position);
30530 auto len_read = buffer.copy(ptr, size, position);
30532 position +=
static_cast<size_t>(len_read);
30533 return static_cast<ssize_t
>(len_read);
30536inline ssize_t BufferStream::write(
const char *ptr,
size_t size) {
30537 buffer.append(ptr, size);
30538 return static_cast<ssize_t
>(size);
30541inline void BufferStream::get_remote_ip_and_port(std::string & ,
30544inline void BufferStream::get_local_ip_and_port(std::string & ,
30547inline socket_t BufferStream::socket()
const {
return 0; }
30549inline const std::string &BufferStream::get_buffer()
const {
return buffer; }
30551inline PathParamsMatcher::PathParamsMatcher(
const std::string &pattern) {
30553 std::size_t last_param_end = 0;
30555#ifndef CPPHTTPLIB_NO_EXCEPTIONS
30560 std::unordered_set<std::string> param_name_set;
30564 const auto marker_pos = pattern.find(marker, last_param_end);
30565 if (marker_pos == std::string::npos) {
break; }
30567 static_fragments_.push_back(
30568 pattern.substr(last_param_end, marker_pos - last_param_end));
30570 const auto param_name_start = marker_pos + 1;
30572 auto sep_pos = pattern.find(separator, param_name_start);
30573 if (sep_pos == std::string::npos) { sep_pos = pattern.length(); }
30576 pattern.substr(param_name_start, sep_pos - param_name_start);
30578#ifndef CPPHTTPLIB_NO_EXCEPTIONS
30579 if (param_name_set.find(param_name) != param_name_set.cend()) {
30580 std::string msg =
"Encountered path parameter '" + param_name +
30581 "' multiple times in route pattern '" + pattern +
"'.";
30582 throw std::invalid_argument(msg);
30586 param_names_.push_back(std::move(param_name));
30588 last_param_end = sep_pos + 1;
30591 if (last_param_end < pattern.length()) {
30592 static_fragments_.push_back(pattern.substr(last_param_end));
30596inline bool PathParamsMatcher::match(Request &request)
const {
30597 request.matches = std::smatch();
30598 request.path_params.clear();
30599 request.path_params.reserve(param_names_.size());
30602 std::size_t starting_pos = 0;
30603 for (
size_t i = 0; i < static_fragments_.size(); ++i) {
30604 const auto &fragment = static_fragments_[i];
30606 if (starting_pos + fragment.length() > request.path.length()) {
30612 if (std::strncmp(request.path.c_str() + starting_pos, fragment.c_str(),
30613 fragment.length()) != 0) {
30617 starting_pos += fragment.length();
30622 if (i >= param_names_.size()) {
continue; }
30624 auto sep_pos = request.path.find(separator, starting_pos);
30625 if (sep_pos == std::string::npos) { sep_pos = request.path.length(); }
30627 const auto ¶m_name = param_names_[i];
30629 request.path_params.emplace(
30630 param_name, request.path.substr(starting_pos, sep_pos - starting_pos));
30633 starting_pos = sep_pos + 1;
30636 return starting_pos >= request.path.length();
30639inline bool RegexMatcher::match(Request &request)
const {
30640 request.path_params.clear();
30641 return std::regex_match(request.path, request.matches, regex_);
30647inline Server::Server()
30649 [] {
return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }) {
30651 signal(SIGPIPE, SIG_IGN);
30655inline Server::~Server() =
default;
30657inline std::unique_ptr<detail::MatcherBase>
30658Server::make_matcher(
const std::string &pattern) {
30659 if (pattern.find(
"/:") != std::string::npos) {
30660 return detail::make_unique<detail::PathParamsMatcher>(pattern);
30662 return detail::make_unique<detail::RegexMatcher>(pattern);
30666inline Server &Server::Get(
const std::string &pattern, Handler handler) {
30667 get_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
30671inline Server &Server::Post(
const std::string &pattern, Handler handler) {
30672 post_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
30676inline Server &Server::Post(
const std::string &pattern,
30677 HandlerWithContentReader handler) {
30678 post_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
30679 std::move(handler));
30683inline Server &Server::Put(
const std::string &pattern, Handler handler) {
30684 put_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
30688inline Server &Server::Put(
const std::string &pattern,
30689 HandlerWithContentReader handler) {
30690 put_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
30691 std::move(handler));
30695inline Server &Server::Patch(
const std::string &pattern, Handler handler) {
30696 patch_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
30700inline Server &Server::Patch(
const std::string &pattern,
30701 HandlerWithContentReader handler) {
30702 patch_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
30703 std::move(handler));
30707inline Server &Server::Delete(
const std::string &pattern, Handler handler) {
30708 delete_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
30712inline Server &Server::Delete(
const std::string &pattern,
30713 HandlerWithContentReader handler) {
30714 delete_handlers_for_content_reader_.emplace_back(make_matcher(pattern),
30715 std::move(handler));
30719inline Server &Server::Options(
const std::string &pattern, Handler handler) {
30720 options_handlers_.emplace_back(make_matcher(pattern), std::move(handler));
30724inline bool Server::set_base_dir(
const std::string &dir,
30725 const std::string &mount_point) {
30726 return set_mount_point(mount_point, dir);
30729inline bool Server::set_mount_point(
const std::string &mount_point,
30730 const std::string &dir, Headers headers) {
30731 if (detail::is_dir(dir)) {
30732 std::string mnt = !mount_point.empty() ? mount_point :
"/";
30733 if (!mnt.empty() && mnt[0] ==
'/') {
30734 base_dirs_.push_back({mnt, dir, std::move(headers)});
30741inline bool Server::remove_mount_point(
const std::string &mount_point) {
30742 for (
auto it = base_dirs_.begin(); it != base_dirs_.end(); ++it) {
30743 if (it->mount_point == mount_point) {
30744 base_dirs_.erase(it);
30752Server::set_file_extension_and_mimetype_mapping(
const std::string &ext,
30753 const std::string &mime) {
30754 file_extension_and_mimetype_map_[ext] = mime;
30758inline Server &Server::set_default_file_mimetype(
const std::string &mime) {
30759 default_file_mimetype_ = mime;
30763inline Server &Server::set_file_request_handler(Handler handler) {
30764 file_request_handler_ = std::move(handler);
30768inline Server &Server::set_error_handler_core(HandlerWithResponse handler,
30770 error_handler_ = std::move(handler);
30774inline Server &Server::set_error_handler_core(Handler handler,
30776 error_handler_ = [handler](
const Request &req, Response &res) {
30778 return HandlerResponse::Handled;
30783inline Server &Server::set_exception_handler(ExceptionHandler handler) {
30784 exception_handler_ = std::move(handler);
30788inline Server &Server::set_pre_routing_handler(HandlerWithResponse handler) {
30789 pre_routing_handler_ = std::move(handler);
30793inline Server &Server::set_post_routing_handler(Handler handler) {
30794 post_routing_handler_ = std::move(handler);
30798inline Server &Server::set_logger(Logger logger) {
30799 logger_ = std::move(logger);
30804Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) {
30805 expect_100_continue_handler_ = std::move(handler);
30809inline Server &Server::set_address_family(
int family) {
30810 address_family_ = family;
30814inline Server &Server::set_tcp_nodelay(
bool on) {
30819inline Server &Server::set_socket_options(SocketOptions socket_options) {
30820 socket_options_ = std::move(socket_options);
30824inline Server &Server::set_default_headers(Headers headers) {
30825 default_headers_ = std::move(headers);
30829inline Server &Server::set_header_writer(
30830 std::function<ssize_t(Stream &, Headers &)>
const &writer) {
30831 header_writer_ = writer;
30835inline Server &Server::set_keep_alive_max_count(
size_t count) {
30836 keep_alive_max_count_ = count;
30840inline Server &Server::set_keep_alive_timeout(time_t sec) {
30841 keep_alive_timeout_sec_ = sec;
30845inline Server &Server::set_read_timeout(time_t sec, time_t usec) {
30846 read_timeout_sec_ = sec;
30847 read_timeout_usec_ = usec;
30851inline Server &Server::set_write_timeout(time_t sec, time_t usec) {
30852 write_timeout_sec_ = sec;
30853 write_timeout_usec_ = usec;
30857inline Server &Server::set_idle_interval(time_t sec, time_t usec) {
30858 idle_interval_sec_ = sec;
30859 idle_interval_usec_ = usec;
30863inline Server &Server::set_payload_max_length(
size_t length) {
30864 payload_max_length_ = length;
30868inline bool Server::bind_to_port(
const std::string &host,
int port,
30869 int socket_flags) {
30870 return bind_internal(host, port, socket_flags) >= 0;
30872inline int Server::bind_to_any_port(
const std::string &host,
int socket_flags) {
30873 return bind_internal(host, 0, socket_flags);
30876inline bool Server::listen_after_bind() {
30877 auto se = detail::scope_exit([&]() { done_ =
true; });
30878 return listen_internal();
30881inline bool Server::listen(
const std::string &host,
int port,
30882 int socket_flags) {
30883 auto se = detail::scope_exit([&]() { done_ =
true; });
30884 return bind_to_port(host, port, socket_flags) && listen_internal();
30887inline bool Server::is_running()
const {
return is_running_; }
30889inline void Server::wait_until_ready()
const {
30890 while (!is_running() && !done_) {
30891 std::this_thread::sleep_for(std::chrono::milliseconds{1});
30895inline void Server::stop() {
30897 assert(svr_sock_ != INVALID_SOCKET);
30898 std::atomic<socket_t> sock(svr_sock_.exchange(INVALID_SOCKET));
30899 detail::shutdown_socket(sock);
30900 detail::close_socket(sock);
30904inline bool Server::parse_request_line(
const char *s, Request &req)
const {
30905 auto len = strlen(s);
30906 if (len < 2 || s[len - 2] !=
'\r' || s[len - 1] !=
'\n') {
return false; }
30912 detail::split(s, s + len,
' ', [&](
const char *b,
const char *e) {
30914 case 0: req.method = std::string(b, e);
break;
30915 case 1: req.target = std::string(b, e);
break;
30916 case 2: req.version = std::string(b, e);
break;
30922 if (count != 3) {
return false; }
30925 static const std::set<std::string> methods{
30926 "GET",
"HEAD",
"POST",
"PUT",
"DELETE",
30927 "CONNECT",
"OPTIONS",
"TRACE",
"PATCH",
"PRI"};
30929 if (methods.find(req.method) == methods.end()) {
return false; }
30931 if (req.version !=
"HTTP/1.1" && req.version !=
"HTTP/1.0") {
return false; }
30935 for (
size_t i = 0; i < req.target.size(); i++) {
30936 if (req.target[i] ==
'#') {
30937 req.target.erase(i);
30942 detail::divide(req.target,
'?',
30943 [&](
const char *lhs_data, std::size_t lhs_size,
30944 const char *rhs_data, std::size_t rhs_size) {
30945 req.path = detail::decode_url(
30946 std::string(lhs_data, lhs_size), false);
30947 detail::parse_query_text(rhs_data, rhs_size, req.params);
30954inline bool Server::write_response(Stream &strm,
bool close_connection,
30955 Request &req, Response &res) {
30958 req.ranges.clear();
30959 return write_response_core(strm, close_connection, req, res,
false);
30962inline bool Server::write_response_with_content(Stream &strm,
30963 bool close_connection,
30964 const Request &req,
30966 return write_response_core(strm, close_connection, req, res,
true);
30969inline bool Server::write_response_core(Stream &strm,
bool close_connection,
30970 const Request &req, Response &res,
30971 bool need_apply_ranges) {
30972 assert(res.status != -1);
30974 if (400 <= res.status && error_handler_ &&
30975 error_handler_(req, res) == HandlerResponse::Handled) {
30976 need_apply_ranges =
true;
30979 std::string content_type;
30980 std::string boundary;
30981 if (need_apply_ranges) { apply_ranges(req, res, content_type, boundary); }
30984 if (close_connection || req.get_header_value(
"Connection") ==
"close") {
30985 res.set_header(
"Connection",
"close");
30987 std::stringstream ss;
30988 ss <<
"timeout=" << keep_alive_timeout_sec_
30989 <<
", max=" << keep_alive_max_count_;
30990 res.set_header(
"Keep-Alive", ss.str());
30993 if (!res.has_header(
"Content-Type") &&
30994 (!res.body.empty() || res.content_length_ > 0 || res.content_provider_)) {
30995 res.set_header(
"Content-Type",
"text/plain");
30998 if (!res.has_header(
"Content-Length") && res.body.empty() &&
30999 !res.content_length_ && !res.content_provider_) {
31000 res.set_header(
"Content-Length",
"0");
31003 if (!res.has_header(
"Accept-Ranges") && req.method ==
"HEAD") {
31004 res.set_header(
"Accept-Ranges",
"bytes");
31007 if (post_routing_handler_) { post_routing_handler_(req, res); }
31011 detail::BufferStream bstrm;
31013 if (!bstrm.write_format(
"HTTP/1.1 %d %s\r\n", res.status,
31014 status_message(res.status))) {
31018 if (!header_writer_(bstrm, res.headers)) {
return false; }
31021 auto &data = bstrm.get_buffer();
31022 detail::write_data(strm, data.data(), data.size());
31027 if (req.method !=
"HEAD") {
31028 if (!res.body.empty()) {
31029 if (!detail::write_data(strm, res.body.data(), res.body.size())) {
31032 }
else if (res.content_provider_) {
31033 if (write_content_with_provider(strm, req, res, boundary, content_type)) {
31034 res.content_provider_success_ =
true;
31042 if (logger_) { logger_(req, res); }
31048Server::write_content_with_provider(Stream &strm,
const Request &req,
31049 Response &res,
const std::string &boundary,
31050 const std::string &content_type) {
31051 auto is_shutting_down = [
this]() {
31052 return this->svr_sock_ == INVALID_SOCKET;
31055 if (res.content_length_ > 0) {
31056 if (req.ranges.empty()) {
31057 return detail::write_content(strm, res.content_provider_, 0,
31058 res.content_length_, is_shutting_down);
31059 }
else if (req.ranges.size() == 1) {
31060 auto offset_and_length = detail::get_range_offset_and_length(
31061 req.ranges[0], res.content_length_);
31063 return detail::write_content(strm, res.content_provider_,
31064 offset_and_length.first,
31065 offset_and_length.second, is_shutting_down);
31067 return detail::write_multipart_ranges_data(
31068 strm, req, res, boundary, content_type, res.content_length_,
31072 if (res.is_chunked_content_provider_) {
31073 auto type = detail::encoding_type(req, res);
31075 std::unique_ptr<detail::compressor> compressor;
31076 if (type == detail::EncodingType::Gzip) {
31077#ifdef CPPHTTPLIB_ZLIB_SUPPORT
31078 compressor = detail::make_unique<detail::gzip_compressor>();
31080 }
else if (type == detail::EncodingType::Brotli) {
31081#ifdef CPPHTTPLIB_BROTLI_SUPPORT
31082 compressor = detail::make_unique<detail::brotli_compressor>();
31085 compressor = detail::make_unique<detail::nocompressor>();
31087 assert(compressor !=
nullptr);
31089 return detail::write_content_chunked(strm, res.content_provider_,
31090 is_shutting_down, *compressor);
31092 return detail::write_content_without_length(strm, res.content_provider_,
31098inline bool Server::read_content(Stream &strm, Request &req, Response &res) {
31099 MultipartFormDataMap::iterator cur;
31100 auto file_count = 0;
31101 if (read_content_core(
31104 [&](
const char *buf,
size_t n) {
31105 if (req.body.size() + n > req.body.max_size()) { return false; }
31106 req.body.append(buf, n);
31110 [&](
const MultipartFormData &file) {
31111 if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) {
31114 cur = req.files.emplace(file.name, file);
31117 [&](
const char *buf,
size_t n) {
31118 auto &content = cur->second.content;
31119 if (content.size() + n > content.max_size()) {
return false; }
31120 content.append(buf, n);
31123 const auto &content_type = req.get_header_value(
"Content-Type");
31124 if (!content_type.find(
"application/x-www-form-urlencoded")) {
31125 if (req.body.size() > CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH) {
31126 res.status = StatusCode::PayloadTooLarge_413;
31129 detail::parse_query_text(req.body, req.params);
31136inline bool Server::read_content_with_content_receiver(
31137 Stream &strm, Request &req, Response &res, ContentReceiver receiver,
31138 MultipartContentHeader multipart_header,
31139 ContentReceiver multipart_receiver) {
31140 return read_content_core(strm, req, res, std::move(receiver),
31141 std::move(multipart_header),
31142 std::move(multipart_receiver));
31146Server::read_content_core(Stream &strm, Request &req, Response &res,
31147 ContentReceiver receiver,
31148 MultipartContentHeader multipart_header,
31149 ContentReceiver multipart_receiver)
const {
31150 detail::MultipartFormDataParser multipart_form_data_parser;
31151 ContentReceiverWithProgress out;
31153 if (req.is_multipart_form_data()) {
31154 const auto &content_type = req.get_header_value(
"Content-Type");
31155 std::string boundary;
31156 if (!detail::parse_multipart_boundary(content_type, boundary)) {
31157 res.status = StatusCode::BadRequest_400;
31161 multipart_form_data_parser.set_boundary(std::move(boundary));
31162 out = [&](
const char *buf,
size_t n, uint64_t , uint64_t ) {
31174 return multipart_form_data_parser.parse(buf, n, multipart_receiver,
31178 out = [receiver](
const char *buf,
size_t n, uint64_t ,
31179 uint64_t ) {
return receiver(buf, n); };
31182 if (req.method ==
"DELETE" && !req.has_header(
"Content-Length")) {
31186 if (!detail::read_content(strm, req, payload_max_length_, res.status,
nullptr,
31191 if (req.is_multipart_form_data()) {
31192 if (!multipart_form_data_parser.is_valid()) {
31193 res.status = StatusCode::BadRequest_400;
31201inline bool Server::handle_file_request(
const Request &req, Response &res,
31203 for (
const auto &entry : base_dirs_) {
31205 if (!req.path.compare(0, entry.mount_point.size(), entry.mount_point)) {
31206 std::string sub_path =
"/" + req.path.substr(entry.mount_point.size());
31207 if (detail::is_valid_path(sub_path)) {
31208 auto path = entry.base_dir + sub_path;
31209 if (path.back() ==
'/') { path +=
"index.html"; }
31211 if (detail::is_file(path)) {
31212 for (
const auto &kv : entry.headers) {
31213 res.set_header(kv.first, kv.second);
31216 auto mm = std::make_shared<detail::mmap>(path.c_str());
31217 if (!mm->is_open()) {
return false; }
31219 res.set_content_provider(
31221 detail::find_content_type(path, file_extension_and_mimetype_map_,
31222 default_file_mimetype_),
31223 [mm](
size_t offset,
size_t length, DataSink &sink) ->
bool {
31224 sink.write(mm->data() + offset, length);
31228 if (!head && file_request_handler_) {
31229 file_request_handler_(req, res);
31241Server::create_server_socket(
const std::string &host,
int port,
31243 SocketOptions socket_options)
const {
31244 return detail::create_socket(
31245 host, std::string(), port, address_family_, socket_flags, tcp_nodelay_,
31246 std::move(socket_options),
31247 [](socket_t sock,
struct addrinfo &ai) ->
bool {
31248 if (::bind(sock, ai.ai_addr,
static_cast<socklen_t
>(ai.ai_addrlen))) {
31251 if (::listen(sock, CPPHTTPLIB_LISTEN_BACKLOG)) {
return false; }
31256inline int Server::bind_internal(
const std::string &host,
int port,
31257 int socket_flags) {
31258 if (!is_valid()) {
return -1; }
31260 svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_);
31261 if (svr_sock_ == INVALID_SOCKET) {
return -1; }
31264 struct sockaddr_storage addr;
31265 socklen_t addr_len =
sizeof(addr);
31266 if (getsockname(svr_sock_,
reinterpret_cast<struct sockaddr *
>(&addr),
31267 &addr_len) == -1) {
31270 if (addr.ss_family == AF_INET) {
31271 return ntohs(
reinterpret_cast<struct sockaddr_in *
>(&addr)->sin_port);
31272 }
else if (addr.ss_family == AF_INET6) {
31273 return ntohs(
reinterpret_cast<struct sockaddr_in6 *
>(&addr)->sin6_port);
31282inline bool Server::listen_internal() {
31284 is_running_ =
true;
31285 auto se = detail::scope_exit([&]() { is_running_ =
false; });
31288 std::unique_ptr<TaskQueue> task_queue(new_task_queue());
31290 while (svr_sock_ != INVALID_SOCKET) {
31292 if (idle_interval_sec_ > 0 || idle_interval_usec_ > 0) {
31294 auto val = detail::select_read(svr_sock_, idle_interval_sec_,
31295 idle_interval_usec_);
31297 task_queue->on_idle();
31303 socket_t sock = accept(svr_sock_,
nullptr,
nullptr);
31305 if (sock == INVALID_SOCKET) {
31306 if (errno == EMFILE) {
31309 std::this_thread::sleep_for(std::chrono::milliseconds(1));
31311 }
else if (errno == EINTR || errno == EAGAIN) {
31314 if (svr_sock_ != INVALID_SOCKET) {
31315 detail::close_socket(svr_sock_);
31325 auto timeout =
static_cast<uint32_t
>(read_timeout_sec_ * 1000 +
31326 read_timeout_usec_ / 1000);
31327 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
31328 reinterpret_cast<const char *
>(&timeout),
sizeof(timeout));
31331 tv.tv_sec =
static_cast<long>(read_timeout_sec_);
31332 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(read_timeout_usec_);
31333 setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
31334 reinterpret_cast<const void *
>(&tv),
sizeof(tv));
31340 auto timeout =
static_cast<uint32_t
>(write_timeout_sec_ * 1000 +
31341 write_timeout_usec_ / 1000);
31342 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
31343 reinterpret_cast<const char *
>(&timeout),
sizeof(timeout));
31346 tv.tv_sec =
static_cast<long>(write_timeout_sec_);
31347 tv.tv_usec =
static_cast<decltype(tv.tv_usec)
>(write_timeout_usec_);
31348 setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
31349 reinterpret_cast<const void *
>(&tv),
sizeof(tv));
31353 if (!task_queue->enqueue(
31354 [
this, sock]() { process_and_close_socket(sock); })) {
31355 detail::shutdown_socket(sock);
31356 detail::close_socket(sock);
31360 task_queue->shutdown();
31366inline bool Server::routing(Request &req, Response &res, Stream &strm) {
31367 if (pre_routing_handler_ &&
31368 pre_routing_handler_(req, res) == HandlerResponse::Handled) {
31373 auto is_head_request = req.method ==
"HEAD";
31374 if ((req.method ==
"GET" || is_head_request) &&
31375 handle_file_request(req, res, is_head_request)) {
31379 if (detail::expect_content(req)) {
31382 ContentReader reader(
31383 [&](ContentReceiver receiver) {
31384 return read_content_with_content_receiver(
31385 strm, req, res, std::move(receiver),
nullptr,
nullptr);
31387 [&](MultipartContentHeader header, ContentReceiver receiver) {
31388 return read_content_with_content_receiver(strm, req, res,
nullptr,
31390 std::move(receiver));
31393 if (req.method ==
"POST") {
31394 if (dispatch_request_for_content_reader(
31395 req, res, std::move(reader),
31396 post_handlers_for_content_reader_)) {
31399 }
else if (req.method ==
"PUT") {
31400 if (dispatch_request_for_content_reader(
31401 req, res, std::move(reader),
31402 put_handlers_for_content_reader_)) {
31405 }
else if (req.method ==
"PATCH") {
31406 if (dispatch_request_for_content_reader(
31407 req, res, std::move(reader),
31408 patch_handlers_for_content_reader_)) {
31411 }
else if (req.method ==
"DELETE") {
31412 if (dispatch_request_for_content_reader(
31413 req, res, std::move(reader),
31414 delete_handlers_for_content_reader_)) {
31421 if (!read_content(strm, req, res)) {
return false; }
31425 if (req.method ==
"GET" || req.method ==
"HEAD") {
31426 return dispatch_request(req, res, get_handlers_);
31427 }
else if (req.method ==
"POST") {
31428 return dispatch_request(req, res, post_handlers_);
31429 }
else if (req.method ==
"PUT") {
31430 return dispatch_request(req, res, put_handlers_);
31431 }
else if (req.method ==
"DELETE") {
31432 return dispatch_request(req, res, delete_handlers_);
31433 }
else if (req.method ==
"OPTIONS") {
31434 return dispatch_request(req, res, options_handlers_);
31435 }
else if (req.method ==
"PATCH") {
31436 return dispatch_request(req, res, patch_handlers_);
31439 res.status = StatusCode::BadRequest_400;
31443inline bool Server::dispatch_request(Request &req, Response &res,
31444 const Handlers &handlers)
const {
31445 for (
const auto &x : handlers) {
31446 const auto &matcher = x.first;
31447 const auto &handler = x.second;
31449 if (matcher->match(req)) {
31457inline void Server::apply_ranges(
const Request &req, Response &res,
31458 std::string &content_type,
31459 std::string &boundary)
const {
31460 if (req.ranges.size() > 1 && res.status == StatusCode::PartialContent_206) {
31461 auto it = res.headers.find(
"Content-Type");
31462 if (it != res.headers.end()) {
31463 content_type = it->second;
31464 res.headers.erase(it);
31467 boundary = detail::make_multipart_data_boundary();
31469 res.set_header(
"Content-Type",
31470 "multipart/byteranges; boundary=" + boundary);
31473 auto type = detail::encoding_type(req, res);
31475 if (res.body.empty()) {
31476 if (res.content_length_ > 0) {
31478 if (req.ranges.empty() || res.status != StatusCode::PartialContent_206) {
31479 length = res.content_length_;
31480 }
else if (req.ranges.size() == 1) {
31481 auto offset_and_length = detail::get_range_offset_and_length(
31482 req.ranges[0], res.content_length_);
31484 length = offset_and_length.second;
31486 auto content_range = detail::make_content_range_header_field(
31487 offset_and_length, res.content_length_);
31488 res.set_header(
"Content-Range", content_range);
31490 length = detail::get_multipart_ranges_data_length(
31491 req, boundary, content_type, res.content_length_);
31493 res.set_header(
"Content-Length", std::to_string(length));
31495 if (res.content_provider_) {
31496 if (res.is_chunked_content_provider_) {
31497 res.set_header(
"Transfer-Encoding",
"chunked");
31498 if (type == detail::EncodingType::Gzip) {
31499 res.set_header(
"Content-Encoding",
"gzip");
31500 }
else if (type == detail::EncodingType::Brotli) {
31501 res.set_header(
"Content-Encoding",
"br");
31507 if (req.ranges.empty() || res.status != StatusCode::PartialContent_206) {
31509 }
else if (req.ranges.size() == 1) {
31510 auto offset_and_length =
31511 detail::get_range_offset_and_length(req.ranges[0], res.body.size());
31512 auto offset = offset_and_length.first;
31513 auto length = offset_and_length.second;
31515 auto content_range = detail::make_content_range_header_field(
31516 offset_and_length, res.body.size());
31517 res.set_header(
"Content-Range", content_range);
31519 assert(offset + length <= res.body.size());
31520 res.body = res.body.substr(offset, length);
31523 detail::make_multipart_ranges_data(req, res, boundary, content_type,
31524 res.body.size(), data);
31525 res.body.swap(data);
31528 if (type != detail::EncodingType::None) {
31529 std::unique_ptr<detail::compressor> compressor;
31530 std::string content_encoding;
31532 if (type == detail::EncodingType::Gzip) {
31533#ifdef CPPHTTPLIB_ZLIB_SUPPORT
31534 compressor = detail::make_unique<detail::gzip_compressor>();
31535 content_encoding =
"gzip";
31537 }
else if (type == detail::EncodingType::Brotli) {
31538#ifdef CPPHTTPLIB_BROTLI_SUPPORT
31539 compressor = detail::make_unique<detail::brotli_compressor>();
31540 content_encoding =
"br";
31545 std::string compressed;
31546 if (compressor->compress(res.body.data(), res.body.size(),
true,
31547 [&](
const char *data,
size_t data_len) {
31548 compressed.append(data, data_len);
31551 res.body.swap(compressed);
31552 res.set_header(
"Content-Encoding", content_encoding);
31557 auto length = std::to_string(res.body.size());
31558 res.set_header(
"Content-Length", length);
31562inline bool Server::dispatch_request_for_content_reader(
31563 Request &req, Response &res, ContentReader content_reader,
31564 const HandlersForContentReader &handlers)
const {
31565 for (
const auto &x : handlers) {
31566 const auto &matcher = x.first;
31567 const auto &handler = x.second;
31569 if (matcher->match(req)) {
31570 handler(req, res, content_reader);
31578Server::process_request(Stream &strm,
bool close_connection,
31579 bool &connection_closed,
31580 const std::function<
void(Request &)> &setup_request) {
31581 std::array<char, 2048> buf{};
31583 detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
31586 if (!line_reader.getline()) {
return false; }
31591 res.version =
"HTTP/1.1";
31592 res.headers = default_headers_;
31597#ifndef CPPHTTPLIB_USE_POLL
31599 if (strm.socket() >= FD_SETSIZE) {
31601 detail::read_headers(strm, dummy);
31602 res.status = StatusCode::InternalServerError_500;
31603 return write_response(strm, close_connection, req, res);
31609 if (line_reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) {
31611 detail::read_headers(strm, dummy);
31612 res.status = StatusCode::UriTooLong_414;
31613 return write_response(strm, close_connection, req, res);
31617 if (!parse_request_line(line_reader.ptr(), req) ||
31618 !detail::read_headers(strm, req.headers)) {
31619 res.status = StatusCode::BadRequest_400;
31620 return write_response(strm, close_connection, req, res);
31623 if (req.get_header_value(
"Connection") ==
"close") {
31624 connection_closed =
true;
31627 if (req.version ==
"HTTP/1.0" &&
31628 req.get_header_value(
"Connection") !=
"Keep-Alive") {
31629 connection_closed =
true;
31632 strm.get_remote_ip_and_port(req.remote_addr, req.remote_port);
31633 req.set_header(
"REMOTE_ADDR", req.remote_addr);
31634 req.set_header(
"REMOTE_PORT", std::to_string(req.remote_port));
31636 strm.get_local_ip_and_port(req.local_addr, req.local_port);
31637 req.set_header(
"LOCAL_ADDR", req.local_addr);
31638 req.set_header(
"LOCAL_PORT", std::to_string(req.local_port));
31640 if (req.has_header(
"Range")) {
31641 const auto &range_header_value = req.get_header_value(
"Range");
31642 if (!detail::parse_range_header(range_header_value, req.ranges)) {
31643 res.status = StatusCode::RangeNotSatisfiable_416;
31644 return write_response(strm, close_connection, req, res);
31648 if (setup_request) { setup_request(req); }
31650 if (req.get_header_value(
"Expect") ==
"100-continue") {
31651 int status = StatusCode::Continue_100;
31652 if (expect_100_continue_handler_) {
31653 status = expect_100_continue_handler_(req, res);
31656 case StatusCode::Continue_100:
31657 case StatusCode::ExpectationFailed_417:
31658 strm.write_format(
"HTTP/1.1 %d %s\r\n\r\n", status,
31659 status_message(status));
31661 default:
return write_response(strm, close_connection, req, res);
31666 auto routed =
false;
31667#ifdef CPPHTTPLIB_NO_EXCEPTIONS
31668 routed = routing(req, res, strm);
31671 routed = routing(req, res, strm);
31672 }
catch (std::exception &e) {
31673 if (exception_handler_) {
31674 auto ep = std::current_exception();
31675 exception_handler_(req, res, ep);
31678 res.status = StatusCode::InternalServerError_500;
31681 for (
size_t i = 0; s[i]; i++) {
31683 case '\r': val +=
"\\r";
break;
31684 case '\n': val +=
"\\n";
break;
31685 default: val += s[i];
break;
31688 res.set_header(
"EXCEPTION_WHAT", val);
31691 if (exception_handler_) {
31692 auto ep = std::current_exception();
31693 exception_handler_(req, res, ep);
31696 res.status = StatusCode::InternalServerError_500;
31697 res.set_header(
"EXCEPTION_WHAT",
"UNKNOWN");
31702 if (res.status == -1) {
31703 res.status = req.ranges.empty() ? StatusCode::OK_200
31704 : StatusCode::PartialContent_206;
31707 if (detail::range_error(req, res)) {
31709 res.content_length_ = 0;
31710 res.content_provider_ =
nullptr;
31711 res.status = StatusCode::RangeNotSatisfiable_416;
31712 return write_response(strm, close_connection, req, res);
31715 return write_response_with_content(strm, close_connection, req, res);
31717 if (res.status == -1) { res.status = StatusCode::NotFound_404; }
31719 return write_response(strm, close_connection, req, res);
31723inline bool Server::is_valid()
const {
return true; }
31725inline bool Server::process_and_close_socket(socket_t sock) {
31726 auto ret = detail::process_server_socket(
31727 svr_sock_, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
31728 read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
31729 write_timeout_usec_,
31730 [
this](Stream &strm,
bool close_connection,
bool &connection_closed) {
31731 return process_request(strm, close_connection, connection_closed,
31735 detail::shutdown_socket(sock);
31736 detail::close_socket(sock);
31741inline ClientImpl::ClientImpl(
const std::string &host)
31742 : ClientImpl(host, 80, std::
string(), std::
string()) {}
31744inline ClientImpl::ClientImpl(
const std::string &host,
int port)
31745 : ClientImpl(host, port, std::
string(), std::
string()) {}
31747inline ClientImpl::ClientImpl(
const std::string &host,
int port,
31748 const std::string &client_cert_path,
31749 const std::string &client_key_path)
31750 : host_(host), port_(port),
31751 host_and_port_(adjust_host_string(host) +
":" + std::to_string(port)),
31752 client_cert_path_(client_cert_path), client_key_path_(client_key_path) {}
31754inline ClientImpl::~ClientImpl() {
31755 std::lock_guard<std::mutex> guard(socket_mutex_);
31756 shutdown_socket(socket_);
31757 close_socket(socket_);
31760inline bool ClientImpl::is_valid()
const {
return true; }
31762inline void ClientImpl::copy_settings(
const ClientImpl &rhs) {
31763 client_cert_path_ = rhs.client_cert_path_;
31764 client_key_path_ = rhs.client_key_path_;
31765 connection_timeout_sec_ = rhs.connection_timeout_sec_;
31766 read_timeout_sec_ = rhs.read_timeout_sec_;
31767 read_timeout_usec_ = rhs.read_timeout_usec_;
31768 write_timeout_sec_ = rhs.write_timeout_sec_;
31769 write_timeout_usec_ = rhs.write_timeout_usec_;
31770 basic_auth_username_ = rhs.basic_auth_username_;
31771 basic_auth_password_ = rhs.basic_auth_password_;
31772 bearer_token_auth_token_ = rhs.bearer_token_auth_token_;
31773#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
31774 digest_auth_username_ = rhs.digest_auth_username_;
31775 digest_auth_password_ = rhs.digest_auth_password_;
31777 keep_alive_ = rhs.keep_alive_;
31778 follow_location_ = rhs.follow_location_;
31779 url_encode_ = rhs.url_encode_;
31780 address_family_ = rhs.address_family_;
31781 tcp_nodelay_ = rhs.tcp_nodelay_;
31782 socket_options_ = rhs.socket_options_;
31783 compress_ = rhs.compress_;
31784 decompress_ = rhs.decompress_;
31785 interface_ = rhs.interface_;
31786 proxy_host_ = rhs.proxy_host_;
31787 proxy_port_ = rhs.proxy_port_;
31788 proxy_basic_auth_username_ = rhs.proxy_basic_auth_username_;
31789 proxy_basic_auth_password_ = rhs.proxy_basic_auth_password_;
31790 proxy_bearer_token_auth_token_ = rhs.proxy_bearer_token_auth_token_;
31791#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
31792 proxy_digest_auth_username_ = rhs.proxy_digest_auth_username_;
31793 proxy_digest_auth_password_ = rhs.proxy_digest_auth_password_;
31795#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
31796 ca_cert_file_path_ = rhs.ca_cert_file_path_;
31797 ca_cert_dir_path_ = rhs.ca_cert_dir_path_;
31798 ca_cert_store_ = rhs.ca_cert_store_;
31800#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
31801 server_certificate_verification_ = rhs.server_certificate_verification_;
31803 logger_ = rhs.logger_;
31806inline socket_t ClientImpl::create_client_socket(Error &error)
const {
31807 if (!proxy_host_.empty() && proxy_port_ != -1) {
31808 return detail::create_client_socket(
31809 proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_,
31810 socket_options_, connection_timeout_sec_, connection_timeout_usec_,
31811 read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
31812 write_timeout_usec_, interface_, error);
31817 auto it = addr_map_.find(host_);
31818 if (it != addr_map_.end()) { ip = it->second; }
31820 return detail::create_client_socket(
31821 host_, ip, port_, address_family_, tcp_nodelay_, socket_options_,
31822 connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_,
31823 read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_,
31827inline bool ClientImpl::create_and_connect_socket(Socket &socket,
31829 auto sock = create_client_socket(error);
31830 if (sock == INVALID_SOCKET) {
return false; }
31831 socket.sock = sock;
31835inline void ClientImpl::shutdown_ssl(Socket & ,
31839 assert(socket_requests_in_flight_ == 0 ||
31840 socket_requests_are_from_thread_ == std::this_thread::get_id());
31843inline void ClientImpl::shutdown_socket(Socket &socket)
const {
31844 if (socket.sock == INVALID_SOCKET) {
return; }
31845 detail::shutdown_socket(socket.sock);
31848inline void ClientImpl::close_socket(Socket &socket) {
31855 assert(socket_requests_in_flight_ == 0 ||
31856 socket_requests_are_from_thread_ == std::this_thread::get_id());
31859#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
31860 assert(socket.ssl ==
nullptr);
31862 if (socket.sock == INVALID_SOCKET) {
return; }
31863 detail::close_socket(socket.sock);
31864 socket.sock = INVALID_SOCKET;
31867inline bool ClientImpl::read_response_line(Stream &strm,
const Request &req,
31868 Response &res)
const {
31869 std::array<char, 2048> buf{};
31871 detail::stream_line_reader line_reader(strm, buf.data(), buf.size());
31873 if (!line_reader.getline()) {
return false; }
31875#ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR
31876 const static std::regex re(
"(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n");
31878 const static std::regex re(
"(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n");
31882 if (!std::regex_match(line_reader.ptr(), m, re)) {
31883 return req.method ==
"CONNECT";
31885 res.version = std::string(m[1]);
31886 res.status = std::stoi(std::string(m[2]));
31887 res.reason = std::string(m[3]);
31890 while (res.status == StatusCode::Continue_100) {
31891 if (!line_reader.getline()) {
return false; }
31892 if (!line_reader.getline()) {
return false; }
31894 if (!std::regex_match(line_reader.ptr(), m, re)) {
return false; }
31895 res.version = std::string(m[1]);
31896 res.status = std::stoi(std::string(m[2]));
31897 res.reason = std::string(m[3]);
31903inline bool ClientImpl::send(Request &req, Response &res, Error &error) {
31904 std::lock_guard<std::recursive_mutex> request_mutex_guard(request_mutex_);
31905 auto ret = send_(req, res, error);
31906 if (error == Error::SSLPeerCouldBeClosed_) {
31908 ret = send_(req, res, error);
31913inline bool ClientImpl::send_(Request &req, Response &res, Error &error) {
31915 std::lock_guard<std::mutex> guard(socket_mutex_);
31919 socket_should_be_closed_when_request_is_done_ =
false;
31921 auto is_alive =
false;
31922 if (socket_.is_open()) {
31923 is_alive = detail::is_socket_alive(socket_.sock);
31929 const bool shutdown_gracefully =
false;
31930 shutdown_ssl(socket_, shutdown_gracefully);
31931 shutdown_socket(socket_);
31932 close_socket(socket_);
31937 if (!create_and_connect_socket(socket_, error)) {
return false; }
31939#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
31942 auto &scli =
static_cast<SSLClient &
>(*this);
31943 if (!proxy_host_.empty() && proxy_port_ != -1) {
31944 auto success =
false;
31945 if (!scli.connect_with_proxy(socket_, res, success, error)) {
31950 if (!scli.initialize_ssl(socket_, error)) {
return false; }
31958 if (socket_requests_in_flight_ > 1) {
31959 assert(socket_requests_are_from_thread_ == std::this_thread::get_id());
31961 socket_requests_in_flight_ += 1;
31962 socket_requests_are_from_thread_ = std::this_thread::get_id();
31965 for (
const auto &header : default_headers_) {
31966 if (req.headers.find(header.first) == req.headers.end()) {
31967 req.headers.insert(header);
31972 auto close_connection = !keep_alive_;
31974 auto se = detail::scope_exit([&]() {
31976 std::lock_guard<std::mutex> guard(socket_mutex_);
31977 socket_requests_in_flight_ -= 1;
31978 if (socket_requests_in_flight_ <= 0) {
31979 assert(socket_requests_in_flight_ == 0);
31980 socket_requests_are_from_thread_ = std::thread::id();
31983 if (socket_should_be_closed_when_request_is_done_ || close_connection ||
31985 shutdown_ssl(socket_,
true);
31986 shutdown_socket(socket_);
31987 close_socket(socket_);
31991 ret = process_socket(socket_, [&](Stream &strm) {
31992 return handle_request(strm, req, res, close_connection, error);
31996 if (error == Error::Success) {
error = Error::Unknown; }
32002inline Result ClientImpl::send(
const Request &req) {
32004 return send_(std::move(req2));
32007inline Result ClientImpl::send_(Request &&req) {
32008 auto res = detail::make_unique<Response>();
32009 auto error = Error::Success;
32010 auto ret = send(req, *res, error);
32011 return Result{ret ? std::move(res) : nullptr,
error, std::move(req.headers)};
32014inline bool ClientImpl::handle_request(Stream &strm, Request &req,
32015 Response &res,
bool close_connection,
32017 if (req.path.empty()) {
32018 error = Error::Connection;
32022 auto req_save = req;
32026 if (!is_ssl() && !proxy_host_.empty() && proxy_port_ != -1) {
32028 req2.path =
"http://" + host_and_port_ + req.path;
32029 ret = process_request(strm, req2, res, close_connection, error);
32031 req.path = req_save.path;
32033 ret = process_request(strm, req, res, close_connection, error);
32036 if (!ret) {
return false; }
32038 if (res.get_header_value(
"Connection") ==
"close" ||
32039 (res.version ==
"HTTP/1.0" && res.reason !=
"Connection established")) {
32047 std::lock_guard<std::mutex> guard(socket_mutex_);
32048 shutdown_ssl(socket_,
true);
32049 shutdown_socket(socket_);
32050 close_socket(socket_);
32053 if (300 < res.status && res.status < 400 && follow_location_) {
32055 ret = redirect(req, res, error);
32058#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
32059 if ((res.status == StatusCode::Unauthorized_401 ||
32060 res.status == StatusCode::ProxyAuthenticationRequired_407) &&
32061 req.authorization_count_ < 5) {
32062 auto is_proxy = res.status == StatusCode::ProxyAuthenticationRequired_407;
32063 const auto &username =
32064 is_proxy ? proxy_digest_auth_username_ : digest_auth_username_;
32065 const auto &password =
32066 is_proxy ? proxy_digest_auth_password_ : digest_auth_password_;
32068 if (!username.empty() && !password.empty()) {
32069 std::map<std::string, std::string> auth;
32070 if (detail::parse_www_authenticate(res, auth, is_proxy)) {
32071 Request new_req = req;
32072 new_req.authorization_count_ += 1;
32073 new_req.headers.erase(is_proxy ?
"Proxy-Authorization"
32074 :
"Authorization");
32075 new_req.headers.insert(detail::make_digest_authentication_header(
32076 req, auth, new_req.authorization_count_, detail::random_string(10),
32077 username, password, is_proxy));
32081 ret = send(new_req, new_res, error);
32082 if (ret) { res = new_res; }
32091inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
32092 if (req.redirect_count_ == 0) {
32093 error = Error::ExceedRedirectCount;
32097 auto location = res.get_header_value(
"location");
32098 if (location.empty()) {
return false; }
32100 const static std::regex re(
32101 R
"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)");
32104 if (!std::regex_match(location, m, re)) {
return false; }
32106 auto scheme = is_ssl() ?
"https" :
"http";
32108 auto next_scheme = m[1].str();
32109 auto next_host = m[2].str();
32110 if (next_host.empty()) { next_host = m[3].str(); }
32111 auto port_str = m[4].str();
32112 auto next_path = m[5].str();
32113 auto next_query = m[6].str();
32115 auto next_port = port_;
32116 if (!port_str.empty()) {
32117 next_port = std::stoi(port_str);
32118 }
else if (!next_scheme.empty()) {
32119 next_port = next_scheme ==
"https" ? 443 : 80;
32122 if (next_scheme.empty()) { next_scheme = scheme; }
32123 if (next_host.empty()) { next_host = host_; }
32124 if (next_path.empty()) { next_path =
"/"; }
32126 auto path = detail::decode_url(next_path,
true) + next_query;
32128 if (next_scheme == scheme && next_host == host_ && next_port == port_) {
32129 return detail::redirect(*
this, req, res, path, location, error);
32131 if (next_scheme ==
"https") {
32132#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
32133 SSLClient cli(next_host, next_port);
32134 cli.copy_settings(*
this);
32135 if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); }
32136 return detail::redirect(cli, req, res, path, location, error);
32141 ClientImpl cli(next_host, next_port);
32142 cli.copy_settings(*
this);
32143 return detail::redirect(cli, req, res, path, location, error);
32148inline bool ClientImpl::write_content_with_provider(Stream &strm,
32149 const Request &req,
32150 Error &error)
const {
32151 auto is_shutting_down = []() {
return false; };
32153 if (req.is_chunked_content_provider_) {
32155 std::unique_ptr<detail::compressor> compressor;
32156#ifdef CPPHTTPLIB_ZLIB_SUPPORT
32158 compressor = detail::make_unique<detail::gzip_compressor>();
32162 compressor = detail::make_unique<detail::nocompressor>();
32165 return detail::write_content_chunked(strm, req.content_provider_,
32166 is_shutting_down, *compressor, error);
32168 return detail::write_content(strm, req.content_provider_, 0,
32169 req.content_length_, is_shutting_down, error);
32173inline bool ClientImpl::write_request(Stream &strm, Request &req,
32174 bool close_connection, Error &error) {
32176 if (close_connection) {
32177 if (!req.has_header(
"Connection")) {
32178 req.set_header(
"Connection",
"close");
32182 if (!req.has_header(
"Host")) {
32184 if (port_ == 443) {
32185 req.set_header(
"Host", host_);
32187 req.set_header(
"Host", host_and_port_);
32191 req.set_header(
"Host", host_);
32193 req.set_header(
"Host", host_and_port_);
32198 if (!req.has_header(
"Accept")) { req.set_header(
"Accept",
"*/*"); }
32200#ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT
32201 if (!req.has_header(
"User-Agent")) {
32202 auto agent = std::string(
"cpp-httplib/") + CPPHTTPLIB_VERSION;
32203 req.set_header(
"User-Agent", agent);
32207 if (req.body.empty()) {
32208 if (req.content_provider_) {
32209 if (!req.is_chunked_content_provider_) {
32210 if (!req.has_header(
"Content-Length")) {
32211 auto length = std::to_string(req.content_length_);
32212 req.set_header(
"Content-Length", length);
32216 if (req.method ==
"POST" || req.method ==
"PUT" ||
32217 req.method ==
"PATCH") {
32218 req.set_header(
"Content-Length",
"0");
32222 if (!req.has_header(
"Content-Type")) {
32223 req.set_header(
"Content-Type",
"text/plain");
32226 if (!req.has_header(
"Content-Length")) {
32227 auto length = std::to_string(req.body.size());
32228 req.set_header(
"Content-Length", length);
32232 if (!basic_auth_password_.empty() || !basic_auth_username_.empty()) {
32233 if (!req.has_header(
"Authorization")) {
32234 req.headers.insert(make_basic_authentication_header(
32235 basic_auth_username_, basic_auth_password_,
false));
32239 if (!proxy_basic_auth_username_.empty() &&
32240 !proxy_basic_auth_password_.empty()) {
32241 if (!req.has_header(
"Proxy-Authorization")) {
32242 req.headers.insert(make_basic_authentication_header(
32243 proxy_basic_auth_username_, proxy_basic_auth_password_,
true));
32247 if (!bearer_token_auth_token_.empty()) {
32248 if (!req.has_header(
"Authorization")) {
32249 req.headers.insert(make_bearer_token_authentication_header(
32250 bearer_token_auth_token_,
false));
32254 if (!proxy_bearer_token_auth_token_.empty()) {
32255 if (!req.has_header(
"Proxy-Authorization")) {
32256 req.headers.insert(make_bearer_token_authentication_header(
32257 proxy_bearer_token_auth_token_,
true));
32263 detail::BufferStream bstrm;
32265 const auto &path = url_encode_ ? detail::encode_url(req.path) : req.path;
32266 bstrm.write_format(
"%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str());
32268 header_writer_(bstrm, req.headers);
32271 auto &data = bstrm.get_buffer();
32272 if (!detail::write_data(strm, data.data(), data.size())) {
32273 error = Error::Write;
32279 if (req.body.empty()) {
32280 return write_content_with_provider(strm, req, error);
32283 if (!detail::write_data(strm, req.body.data(), req.body.size())) {
32284 error = Error::Write;
32291inline std::unique_ptr<Response> ClientImpl::send_with_content_provider(
32292 Request &req,
const char *body,
size_t content_length,
32293 ContentProvider content_provider,
32294 ContentProviderWithoutLength content_provider_without_length,
32295 const std::string &content_type, Error &error, ContentReceiver content_receiver) {
32296 if (!content_type.empty()) { req.set_header(
"Content-Type", content_type); }
32298#ifdef CPPHTTPLIB_ZLIB_SUPPORT
32299 if (compress_) { req.set_header(
"Content-Encoding",
"gzip"); }
32302#ifdef CPPHTTPLIB_ZLIB_SUPPORT
32303 if (compress_ && !content_provider_without_length) {
32305 detail::gzip_compressor compressor;
32307 if (content_provider) {
32310 DataSink data_sink;
32312 data_sink.write = [&](
const char *data,
size_t data_len) ->
bool {
32314 auto last = offset + data_len == content_length;
32316 auto ret = compressor.compress(
32317 data, data_len, last,
32318 [&](
const char *compressed_data,
size_t compressed_data_len) {
32319 req.body.append(compressed_data, compressed_data_len);
32324 offset += data_len;
32332 while (ok && offset < content_length) {
32333 if (!content_provider(offset, content_length - offset, data_sink)) {
32334 error = Error::Canceled;
32339 if (!compressor.compress(body, content_length,
true,
32340 [&](
const char *data,
size_t data_len) {
32341 req.body.append(data, data_len);
32344 error = Error::Compression;
32351 if (content_provider) {
32352 req.content_length_ = content_length;
32353 req.content_provider_ = std::move(content_provider);
32354 req.is_chunked_content_provider_ =
false;
32355 }
else if (content_provider_without_length) {
32356 req.content_length_ = 0;
32357 req.content_provider_ = detail::ContentProviderAdapter(
32358 std::move(content_provider_without_length));
32359 req.is_chunked_content_provider_ =
true;
32360 req.set_header(
"Transfer-Encoding",
"chunked");
32362 req.body.assign(body, content_length);
32366 req.response_handler = std::move(
nullptr);
32367 if (content_receiver) req.content_receiver =
32368 [content_receiver](
const char *data,
size_t data_length,
32369 uint64_t , uint64_t ) {
32370 return content_receiver(data, data_length);
32373 auto res = detail::make_unique<Response>();
32374 return send(req, *res, error) ? std::move(res) : nullptr;
32377inline Result ClientImpl::send_with_content_provider(
32378 const std::string &method,
const std::string &path,
const Headers &headers,
32379 const char *body,
size_t content_length, ContentProvider content_provider,
32380 ContentProviderWithoutLength content_provider_without_length,
32381 const std::string &content_type, Progress progress, ContentReceiver content_receiver) {
32383 req.method = method;
32384 req.headers = headers;
32386 req.progress = progress;
32388 auto error = Error::Success;
32390 auto res = send_with_content_provider(
32391 req, body, content_length, std::move(content_provider),
32392 std::move(content_provider_without_length), content_type, error, std::move(content_receiver));
32394 return Result{std::move(res),
error, std::move(req.headers)};
32398ClientImpl::adjust_host_string(
const std::string &host)
const {
32399 if (host.find(
':') != std::string::npos) {
return "[" + host +
"]"; }
32403inline bool ClientImpl::process_request(Stream &strm, Request &req,
32404 Response &res,
bool close_connection,
32407 if (!write_request(strm, req, close_connection, error)) {
return false; }
32409#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
32411 auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1;
32412 if (!is_proxy_enabled) {
32414 if (SSL_peek(socket_.ssl, buf, 1) == 0 &&
32415 SSL_get_error(socket_.ssl, 0) == SSL_ERROR_ZERO_RETURN) {
32416 error = Error::SSLPeerCouldBeClosed_;
32424 if (!read_response_line(strm, req, res) ||
32425 !detail::read_headers(strm, res.headers)) {
32426 error = Error::Read;
32431 if ((res.status != StatusCode::NoContent_204) && req.method !=
"HEAD" &&
32432 req.method !=
"CONNECT") {
32433 auto redirect = 300 < res.status && res.status < 400 && follow_location_;
32435 if (req.response_handler && !redirect) {
32436 if (!req.response_handler(res)) {
32437 error = Error::Canceled;
32443 req.content_receiver
32444 ?
static_cast<ContentReceiverWithProgress
>(
32445 [&](
const char *buf,
size_t n, uint64_t off, uint64_t len) {
32446 if (redirect) {
return true; }
32447 auto ret = req.content_receiver(buf, n, off, len);
32448 if (!ret) {
error = Error::Canceled; }
32451 : static_cast<ContentReceiverWithProgress>(
32452 [&](const char *buf, size_t n, uint64_t ,
32454 if (res.body.size() + n > res.body.max_size()) {
32457 res.body.append(buf, n);
32461 auto progress = [&](uint64_t current, uint64_t total) {
32462 if (!req.progress || redirect) {
return true; }
32463 auto ret = req.progress(current, total);
32464 if (!ret) {
error = Error::Canceled; }
32469 if (!detail::read_content(strm, res, (std::numeric_limits<size_t>::max)(),
32470 dummy_status, std::move(progress), std::move(out),
32472 if (error != Error::Canceled) {
error = Error::Read; }
32478 if (logger_) { logger_(req, res); }
32483inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider(
32484 const std::string &boundary,
const MultipartFormDataItems &items,
32485 const MultipartFormDataProviderItems &provider_items)
const {
32486 size_t cur_item = 0;
32487 size_t cur_start = 0;
32490 return [&, cur_item, cur_start](
size_t offset,
32491 DataSink &sink)
mutable ->
bool {
32492 if (!offset && !items.empty()) {
32493 sink.os << detail::serialize_multipart_formdata(items, boundary,
false);
32495 }
else if (cur_item < provider_items.size()) {
32497 const auto &begin = detail::serialize_multipart_formdata_item_begin(
32498 provider_items[cur_item], boundary);
32499 offset += begin.size();
32500 cur_start = offset;
32505 auto has_data =
true;
32506 cur_sink.write = sink.write;
32507 cur_sink.done = [&]() { has_data =
false; };
32509 if (!provider_items[cur_item].provider(offset - cur_start, cur_sink)) {
32514 sink.os << detail::serialize_multipart_formdata_item_end();
32520 sink.os << detail::serialize_multipart_formdata_finish(boundary);
32528ClientImpl::process_socket(
const Socket &socket,
32529 std::function<
bool(Stream &strm)> callback) {
32530 return detail::process_client_socket(
32531 socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
32532 write_timeout_usec_, std::move(callback));
32535inline bool ClientImpl::is_ssl()
const {
return false; }
32537inline Result ClientImpl::Get(
const std::string &path) {
32538 return Get(path, Headers(), Progress());
32541inline Result ClientImpl::Get(
const std::string &path, Progress progress) {
32542 return Get(path, Headers(), std::move(progress));
32545inline Result ClientImpl::Get(
const std::string &path,
const Headers &headers) {
32546 return Get(path, headers, Progress());
32549inline Result ClientImpl::Get(
const std::string &path,
const Headers &headers,
32550 Progress progress) {
32552 req.method =
"GET";
32554 req.headers = headers;
32555 req.progress = std::move(progress);
32557 return send_(std::move(req));
32560inline Result ClientImpl::Get(
const std::string &path,
32561 ContentReceiver content_receiver) {
32562 return Get(path, Headers(),
nullptr, std::move(content_receiver),
nullptr);
32565inline Result ClientImpl::Get(
const std::string &path,
32566 ContentReceiver content_receiver,
32567 Progress progress) {
32568 return Get(path, Headers(),
nullptr, std::move(content_receiver),
32569 std::move(progress));
32572inline Result ClientImpl::Get(
const std::string &path,
const Headers &headers,
32573 ContentReceiver content_receiver) {
32574 return Get(path, headers,
nullptr, std::move(content_receiver),
nullptr);
32577inline Result ClientImpl::Get(
const std::string &path,
const Headers &headers,
32578 ContentReceiver content_receiver,
32579 Progress progress) {
32580 return Get(path, headers,
nullptr, std::move(content_receiver),
32581 std::move(progress));
32584inline Result ClientImpl::Get(
const std::string &path,
32585 ResponseHandler response_handler,
32586 ContentReceiver content_receiver) {
32587 return Get(path, Headers(), std::move(response_handler),
32588 std::move(content_receiver),
nullptr);
32591inline Result ClientImpl::Get(
const std::string &path,
const Headers &headers,
32592 ResponseHandler response_handler,
32593 ContentReceiver content_receiver) {
32594 return Get(path, headers, std::move(response_handler),
32595 std::move(content_receiver),
nullptr);
32598inline Result ClientImpl::Get(
const std::string &path,
32599 ResponseHandler response_handler,
32600 ContentReceiver content_receiver,
32601 Progress progress) {
32602 return Get(path, Headers(), std::move(response_handler),
32603 std::move(content_receiver), std::move(progress));
32606inline Result ClientImpl::Get(
const std::string &path,
const Headers &headers,
32607 ResponseHandler response_handler,
32608 ContentReceiver content_receiver,
32609 Progress progress) {
32611 req.method =
"GET";
32613 req.headers = headers;
32614 req.response_handler = std::move(response_handler);
32615 req.content_receiver =
32616 [content_receiver](
const char *data,
size_t data_length,
32617 uint64_t , uint64_t ) {
32618 return content_receiver(data, data_length);
32620 req.progress = std::move(progress);
32622 return send_(std::move(req));
32625inline Result ClientImpl::Get(
const std::string &path,
const Params ¶ms,
32626 const Headers &headers, Progress progress) {
32627 if (params.empty()) {
return Get(path, headers); }
32629 std::string path_with_query = append_query_params(path, params);
32630 return Get(path_with_query, headers, std::move(progress));
32633inline Result ClientImpl::Get(
const std::string &path,
const Params ¶ms,
32634 const Headers &headers,
32635 ContentReceiver content_receiver,
32636 Progress progress) {
32637 return Get(path, params, headers,
nullptr, std::move(content_receiver),
32638 std::move(progress));
32641inline Result ClientImpl::Get(
const std::string &path,
const Params ¶ms,
32642 const Headers &headers,
32643 ResponseHandler response_handler,
32644 ContentReceiver content_receiver,
32645 Progress progress) {
32646 if (params.empty()) {
32647 return Get(path, headers, std::move(response_handler),
32648 std::move(content_receiver), std::move(progress));
32651 std::string path_with_query = append_query_params(path, params);
32652 return Get(path_with_query, headers, std::move(response_handler),
32653 std::move(content_receiver), std::move(progress));
32656inline Result ClientImpl::Head(
const std::string &path) {
32657 return Head(path, Headers());
32660inline Result ClientImpl::Head(
const std::string &path,
32661 const Headers &headers) {
32663 req.method =
"HEAD";
32664 req.headers = headers;
32667 return send_(std::move(req));
32670inline Result ClientImpl::Post(
const std::string &path) {
32671 return Post(path, std::string(), std::string());
32674inline Result ClientImpl::Post(
const std::string &path,
32675 const Headers &headers) {
32676 return Post(path, headers,
nullptr, 0, std::string());
32679inline Result ClientImpl::Post(
const std::string &path,
const char *body,
32680 size_t content_length,
32681 const std::string &content_type) {
32682 return Post(path, Headers(), body, content_length, content_type,
nullptr);
32685inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32686 const char *body,
size_t content_length,
32687 const std::string &content_type) {
32688 return send_with_content_provider(
"POST", path, headers, body, content_length,
32689 nullptr,
nullptr, content_type,
nullptr);
32692inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32693 const char *body,
size_t content_length,
32694 const std::string &content_type,
32695 Progress progress) {
32696 return send_with_content_provider(
"POST", path, headers, body, content_length,
32697 nullptr,
nullptr, content_type, progress);
32700inline Result ClientImpl::Post(
const std::string &path,
const std::string &body,
32701 const std::string &content_type) {
32702 return Post(path, Headers(), body, content_type);
32705inline Result ClientImpl::Post(
const std::string &path,
const std::string &body,
32706 const std::string &content_type, ContentReceiver content_receiver) {
32707 return Post(path, Headers(), body, content_type, std::move(content_receiver));
32710inline Result ClientImpl::Post(
const std::string &path,
const std::string &body,
32711 const std::string &content_type,
32712 Progress progress) {
32713 return Post(path, Headers(), body, content_type, progress);
32716inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32717 const std::string &body,
32718 const std::string &content_type
32720 return send_with_content_provider(
"POST", path, headers, body.data(),
32721 body.size(),
nullptr,
nullptr, content_type,
32725inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32726 const std::string &body,
32727 const std::string &content_type,
32728 ContentReceiver content_receiver) {
32729 return send_with_content_provider(
"POST", path, headers, body.data(),
32730 body.size(),
nullptr,
nullptr, content_type,
32731 nullptr, std::move(content_receiver));
32735inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32736 const std::string &body,
32737 const std::string &content_type,
32738 Progress progress) {
32739 return send_with_content_provider(
"POST", path, headers, body.data(),
32740 body.size(),
nullptr,
nullptr, content_type,
32744inline Result ClientImpl::Post(
const std::string &path,
const Params ¶ms) {
32745 return Post(path, Headers(), params);
32748inline Result ClientImpl::Post(
const std::string &path,
size_t content_length,
32749 ContentProvider content_provider,
32750 const std::string &content_type) {
32751 return Post(path, Headers(), content_length, std::move(content_provider),
32755inline Result ClientImpl::Post(
const std::string &path,
32756 ContentProviderWithoutLength content_provider,
32757 const std::string &content_type) {
32758 return Post(path, Headers(), std::move(content_provider), content_type);
32761inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32762 size_t content_length,
32763 ContentProvider content_provider,
32764 const std::string &content_type) {
32765 return send_with_content_provider(
"POST", path, headers,
nullptr,
32766 content_length, std::move(content_provider),
32767 nullptr, content_type,
nullptr);
32770inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32771 ContentProviderWithoutLength content_provider,
32772 const std::string &content_type) {
32773 return send_with_content_provider(
"POST", path, headers,
nullptr, 0,
nullptr,
32774 std::move(content_provider), content_type,
32778inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32779 const Params ¶ms) {
32780 auto query = detail::params_to_query_str(params);
32781 return Post(path, headers, query,
"application/x-www-form-urlencoded");
32784inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32785 const Params ¶ms, Progress progress) {
32786 auto query = detail::params_to_query_str(params);
32787 return Post(path, headers, query,
"application/x-www-form-urlencoded",
32791inline Result ClientImpl::Post(
const std::string &path,
32792 const MultipartFormDataItems &items) {
32793 return Post(path, Headers(), items);
32796inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32797 const MultipartFormDataItems &items) {
32798 const auto &boundary = detail::make_multipart_data_boundary();
32799 const auto &content_type =
32800 detail::serialize_multipart_formdata_get_content_type(boundary);
32801 const auto &body = detail::serialize_multipart_formdata(items, boundary);
32802 return Post(path, headers, body, content_type);
32805inline Result ClientImpl::Post(
const std::string &path,
const Headers &headers,
32806 const MultipartFormDataItems &items,
32807 const std::string &boundary) {
32808 if (!detail::is_multipart_boundary_chars_valid(boundary)) {
32809 return Result{
nullptr, Error::UnsupportedMultipartBoundaryChars};
32812 const auto &content_type =
32813 detail::serialize_multipart_formdata_get_content_type(boundary);
32814 const auto &body = detail::serialize_multipart_formdata(items, boundary);
32815 return Post(path, headers, body, content_type);
32819ClientImpl::Post(
const std::string &path,
const Headers &headers,
32820 const MultipartFormDataItems &items,
32821 const MultipartFormDataProviderItems &provider_items) {
32822 const auto &boundary = detail::make_multipart_data_boundary();
32823 const auto &content_type =
32824 detail::serialize_multipart_formdata_get_content_type(boundary);
32825 return send_with_content_provider(
32826 "POST", path, headers,
nullptr, 0,
nullptr,
32827 get_multipart_content_provider(boundary, items, provider_items),
32828 content_type,
nullptr);
32831inline Result ClientImpl::Put(
const std::string &path) {
32832 return Put(path, std::string(), std::string());
32835inline Result ClientImpl::Put(
const std::string &path,
const char *body,
32836 size_t content_length,
32837 const std::string &content_type) {
32838 return Put(path, Headers(), body, content_length, content_type);
32841inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32842 const char *body,
size_t content_length,
32843 const std::string &content_type) {
32844 return send_with_content_provider(
"PUT", path, headers, body, content_length,
32845 nullptr,
nullptr, content_type,
nullptr);
32848inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32849 const char *body,
size_t content_length,
32850 const std::string &content_type,
32851 Progress progress) {
32852 return send_with_content_provider(
"PUT", path, headers, body, content_length,
32853 nullptr,
nullptr, content_type, progress);
32856inline Result ClientImpl::Put(
const std::string &path,
const std::string &body,
32857 const std::string &content_type) {
32858 return Put(path, Headers(), body, content_type);
32861inline Result ClientImpl::Put(
const std::string &path,
const std::string &body,
32862 const std::string &content_type,
32863 Progress progress) {
32864 return Put(path, Headers(), body, content_type, progress);
32867inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32868 const std::string &body,
32869 const std::string &content_type) {
32870 return send_with_content_provider(
"PUT", path, headers, body.data(),
32871 body.size(),
nullptr,
nullptr, content_type,
32875inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32876 const std::string &body,
32877 const std::string &content_type,
32878 Progress progress) {
32879 return send_with_content_provider(
"PUT", path, headers, body.data(),
32880 body.size(),
nullptr,
nullptr, content_type,
32884inline Result ClientImpl::Put(
const std::string &path,
size_t content_length,
32885 ContentProvider content_provider,
32886 const std::string &content_type) {
32887 return Put(path, Headers(), content_length, std::move(content_provider),
32891inline Result ClientImpl::Put(
const std::string &path,
32892 ContentProviderWithoutLength content_provider,
32893 const std::string &content_type) {
32894 return Put(path, Headers(), std::move(content_provider), content_type);
32897inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32898 size_t content_length,
32899 ContentProvider content_provider,
32900 const std::string &content_type) {
32901 return send_with_content_provider(
"PUT", path, headers,
nullptr,
32902 content_length, std::move(content_provider),
32903 nullptr, content_type,
nullptr);
32906inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32907 ContentProviderWithoutLength content_provider,
32908 const std::string &content_type) {
32909 return send_with_content_provider(
"PUT", path, headers,
nullptr, 0,
nullptr,
32910 std::move(content_provider), content_type,
32914inline Result ClientImpl::Put(
const std::string &path,
const Params ¶ms) {
32915 return Put(path, Headers(), params);
32918inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32919 const Params ¶ms) {
32920 auto query = detail::params_to_query_str(params);
32921 return Put(path, headers, query,
"application/x-www-form-urlencoded");
32924inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32925 const Params ¶ms, Progress progress) {
32926 auto query = detail::params_to_query_str(params);
32927 return Put(path, headers, query,
"application/x-www-form-urlencoded",
32931inline Result ClientImpl::Put(
const std::string &path,
32932 const MultipartFormDataItems &items) {
32933 return Put(path, Headers(), items);
32936inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32937 const MultipartFormDataItems &items) {
32938 const auto &boundary = detail::make_multipart_data_boundary();
32939 const auto &content_type =
32940 detail::serialize_multipart_formdata_get_content_type(boundary);
32941 const auto &body = detail::serialize_multipart_formdata(items, boundary);
32942 return Put(path, headers, body, content_type);
32945inline Result ClientImpl::Put(
const std::string &path,
const Headers &headers,
32946 const MultipartFormDataItems &items,
32947 const std::string &boundary) {
32948 if (!detail::is_multipart_boundary_chars_valid(boundary)) {
32949 return Result{
nullptr, Error::UnsupportedMultipartBoundaryChars};
32952 const auto &content_type =
32953 detail::serialize_multipart_formdata_get_content_type(boundary);
32954 const auto &body = detail::serialize_multipart_formdata(items, boundary);
32955 return Put(path, headers, body, content_type);
32959ClientImpl::Put(
const std::string &path,
const Headers &headers,
32960 const MultipartFormDataItems &items,
32961 const MultipartFormDataProviderItems &provider_items) {
32962 const auto &boundary = detail::make_multipart_data_boundary();
32963 const auto &content_type =
32964 detail::serialize_multipart_formdata_get_content_type(boundary);
32965 return send_with_content_provider(
32966 "PUT", path, headers,
nullptr, 0,
nullptr,
32967 get_multipart_content_provider(boundary, items, provider_items),
32968 content_type,
nullptr);
32970inline Result ClientImpl::Patch(
const std::string &path) {
32971 return Patch(path, std::string(), std::string());
32974inline Result ClientImpl::Patch(
const std::string &path,
const char *body,
32975 size_t content_length,
32976 const std::string &content_type) {
32977 return Patch(path, Headers(), body, content_length, content_type);
32980inline Result ClientImpl::Patch(
const std::string &path,
const char *body,
32981 size_t content_length,
32982 const std::string &content_type,
32983 Progress progress) {
32984 return Patch(path, Headers(), body, content_length, content_type, progress);
32987inline Result ClientImpl::Patch(
const std::string &path,
const Headers &headers,
32988 const char *body,
size_t content_length,
32989 const std::string &content_type) {
32990 return Patch(path, headers, body, content_length, content_type,
nullptr);
32993inline Result ClientImpl::Patch(
const std::string &path,
const Headers &headers,
32994 const char *body,
size_t content_length,
32995 const std::string &content_type,
32996 Progress progress) {
32997 return send_with_content_provider(
"PATCH", path, headers, body,
32998 content_length,
nullptr,
nullptr,
32999 content_type, progress);
33002inline Result ClientImpl::Patch(
const std::string &path,
33003 const std::string &body,
33004 const std::string &content_type) {
33005 return Patch(path, Headers(), body, content_type);
33008inline Result ClientImpl::Patch(
const std::string &path,
33009 const std::string &body,
33010 const std::string &content_type, Progress progress) {
33011 return Patch(path, Headers(), body, content_type, progress);
33014inline Result ClientImpl::Patch(
const std::string &path,
const Headers &headers,
33015 const std::string &body,
33016 const std::string &content_type) {
33017 return Patch(path, headers, body, content_type,
nullptr);
33020inline Result ClientImpl::Patch(
const std::string &path,
const Headers &headers,
33021 const std::string &body,
33022 const std::string &content_type,
33023 Progress progress) {
33024 return send_with_content_provider(
"PATCH", path, headers, body.data(),
33025 body.size(),
nullptr,
nullptr, content_type,
33029inline Result ClientImpl::Patch(
const std::string &path,
size_t content_length,
33030 ContentProvider content_provider,
33031 const std::string &content_type) {
33032 return Patch(path, Headers(), content_length, std::move(content_provider),
33036inline Result ClientImpl::Patch(
const std::string &path,
33037 ContentProviderWithoutLength content_provider,
33038 const std::string &content_type) {
33039 return Patch(path, Headers(), std::move(content_provider), content_type);
33042inline Result ClientImpl::Patch(
const std::string &path,
const Headers &headers,
33043 size_t content_length,
33044 ContentProvider content_provider,
33045 const std::string &content_type) {
33046 return send_with_content_provider(
"PATCH", path, headers,
nullptr,
33047 content_length, std::move(content_provider),
33048 nullptr, content_type,
nullptr);
33051inline Result ClientImpl::Patch(
const std::string &path,
const Headers &headers,
33052 ContentProviderWithoutLength content_provider,
33053 const std::string &content_type) {
33054 return send_with_content_provider(
"PATCH", path, headers,
nullptr, 0,
nullptr,
33055 std::move(content_provider), content_type,
33059inline Result ClientImpl::Delete(
const std::string &path) {
33060 return Delete(path, Headers(), std::string(), std::string());
33063inline Result ClientImpl::Delete(
const std::string &path,
33064 const Headers &headers) {
33065 return Delete(path, headers, std::string(), std::string());
33068inline Result ClientImpl::Delete(
const std::string &path,
const char *body,
33069 size_t content_length,
33070 const std::string &content_type) {
33071 return Delete(path, Headers(), body, content_length, content_type);
33074inline Result ClientImpl::Delete(
const std::string &path,
const char *body,
33075 size_t content_length,
33076 const std::string &content_type,
33077 Progress progress) {
33078 return Delete(path, Headers(), body, content_length, content_type, progress);
33081inline Result ClientImpl::Delete(
const std::string &path,
33082 const Headers &headers,
const char *body,
33083 size_t content_length,
33084 const std::string &content_type) {
33085 return Delete(path, headers, body, content_length, content_type,
nullptr);
33088inline Result ClientImpl::Delete(
const std::string &path,
33089 const Headers &headers,
const char *body,
33090 size_t content_length,
33091 const std::string &content_type,
33092 Progress progress) {
33094 req.method =
"DELETE";
33095 req.headers = headers;
33097 req.progress = progress;
33099 if (!content_type.empty()) { req.set_header(
"Content-Type", content_type); }
33100 req.body.assign(body, content_length);
33102 return send_(std::move(req));
33105inline Result ClientImpl::Delete(
const std::string &path,
33106 const std::string &body,
33107 const std::string &content_type) {
33108 return Delete(path, Headers(), body.data(), body.size(), content_type);
33111inline Result ClientImpl::Delete(
const std::string &path,
33112 const std::string &body,
33113 const std::string &content_type,
33114 Progress progress) {
33115 return Delete(path, Headers(), body.data(), body.size(), content_type,
33119inline Result ClientImpl::Delete(
const std::string &path,
33120 const Headers &headers,
33121 const std::string &body,
33122 const std::string &content_type) {
33123 return Delete(path, headers, body.data(), body.size(), content_type);
33126inline Result ClientImpl::Delete(
const std::string &path,
33127 const Headers &headers,
33128 const std::string &body,
33129 const std::string &content_type,
33130 Progress progress) {
33131 return Delete(path, headers, body.data(), body.size(), content_type,
33135inline Result ClientImpl::Options(
const std::string &path) {
33136 return Options(path, Headers());
33139inline Result ClientImpl::Options(
const std::string &path,
33140 const Headers &headers) {
33142 req.method =
"OPTIONS";
33143 req.headers = headers;
33146 return send_(std::move(req));
33149inline void ClientImpl::stop() {
33150 std::lock_guard<std::mutex> guard(socket_mutex_);
33157 if (socket_requests_in_flight_ > 0) {
33158 shutdown_socket(socket_);
33162 socket_should_be_closed_when_request_is_done_ =
true;
33167 shutdown_ssl(socket_,
true);
33168 shutdown_socket(socket_);
33169 close_socket(socket_);
33172inline std::string ClientImpl::host()
const {
return host_; }
33174inline int ClientImpl::port()
const {
return port_; }
33176inline size_t ClientImpl::is_socket_open()
const {
33177 std::lock_guard<std::mutex> guard(socket_mutex_);
33178 return socket_.is_open();
33181inline socket_t ClientImpl::socket()
const {
return socket_.sock; }
33183inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) {
33184 connection_timeout_sec_ = sec;
33185 connection_timeout_usec_ = usec;
33188inline void ClientImpl::set_read_timeout(time_t sec, time_t usec) {
33189 read_timeout_sec_ = sec;
33190 read_timeout_usec_ = usec;
33193inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) {
33194 write_timeout_sec_ = sec;
33195 write_timeout_usec_ = usec;
33198inline void ClientImpl::set_basic_auth(
const std::string &username,
33199 const std::string &password) {
33200 basic_auth_username_ = username;
33201 basic_auth_password_ = password;
33204inline void ClientImpl::set_bearer_token_auth(
const std::string &token) {
33205 bearer_token_auth_token_ = token;
33208#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
33209inline void ClientImpl::set_digest_auth(
const std::string &username,
33210 const std::string &password) {
33211 digest_auth_username_ = username;
33212 digest_auth_password_ = password;
33216inline void ClientImpl::set_keep_alive(
bool on) { keep_alive_ = on; }
33218inline void ClientImpl::set_follow_location(
bool on) { follow_location_ = on; }
33220inline void ClientImpl::set_url_encode(
bool on) { url_encode_ = on; }
33223ClientImpl::set_hostname_addr_map(std::map<std::string, std::string> addr_map) {
33224 addr_map_ = std::move(addr_map);
33227inline void ClientImpl::set_default_headers(Headers headers) {
33228 default_headers_ = std::move(headers);
33231inline void ClientImpl::set_header_writer(
33232 std::function<ssize_t(Stream &, Headers &)>
const &writer) {
33233 header_writer_ = writer;
33236inline void ClientImpl::set_address_family(
int family) {
33237 address_family_ = family;
33240inline void ClientImpl::set_tcp_nodelay(
bool on) { tcp_nodelay_ = on; }
33242inline void ClientImpl::set_socket_options(SocketOptions socket_options) {
33243 socket_options_ = std::move(socket_options);
33246inline void ClientImpl::set_compress(
bool on) { compress_ = on; }
33248inline void ClientImpl::set_decompress(
bool on) { decompress_ = on; }
33250inline void ClientImpl::set_interface(
const std::string &intf) {
33254inline void ClientImpl::set_proxy(
const std::string &host,
int port) {
33255 proxy_host_ = host;
33256 proxy_port_ = port;
33259inline void ClientImpl::set_proxy_basic_auth(
const std::string &username,
33260 const std::string &password) {
33261 proxy_basic_auth_username_ = username;
33262 proxy_basic_auth_password_ = password;
33265inline void ClientImpl::set_proxy_bearer_token_auth(
const std::string &token) {
33266 proxy_bearer_token_auth_token_ = token;
33269#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
33270inline void ClientImpl::set_proxy_digest_auth(
const std::string &username,
33271 const std::string &password) {
33272 proxy_digest_auth_username_ = username;
33273 proxy_digest_auth_password_ = password;
33276inline void ClientImpl::set_ca_cert_path(
const std::string &ca_cert_file_path,
33277 const std::string &ca_cert_dir_path) {
33278 ca_cert_file_path_ = ca_cert_file_path;
33279 ca_cert_dir_path_ = ca_cert_dir_path;
33282inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) {
33283 if (ca_cert_store && ca_cert_store != ca_cert_store_) {
33284 ca_cert_store_ = ca_cert_store;
33288inline X509_STORE *ClientImpl::create_ca_cert_store(
const char *ca_cert,
33289 std::size_t size)
const {
33290 auto mem = BIO_new_mem_buf(ca_cert,
static_cast<int>(size));
33291 if (!mem) {
return nullptr; }
33293 auto inf = PEM_X509_INFO_read_bio(mem,
nullptr,
nullptr,
nullptr);
33299 auto cts = X509_STORE_new();
33301 for (
auto i = 0; i < static_cast<int>(sk_X509_INFO_num(inf)); i++) {
33302 auto itmp = sk_X509_INFO_value(inf, i);
33303 if (!itmp) {
continue; }
33305 if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); }
33306 if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); }
33310 sk_X509_INFO_pop_free(inf, X509_INFO_free);
33315inline void ClientImpl::enable_server_certificate_verification(
bool enabled) {
33316 server_certificate_verification_ = enabled;
33320inline void ClientImpl::set_logger(Logger logger) {
33321 logger_ = std::move(logger);
33327#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
33330template <
typename U,
typename V>
33331inline SSL *ssl_new(socket_t sock, SSL_CTX *ctx, std::mutex &ctx_mutex,
33332 U SSL_connect_or_accept, V setup) {
33333 SSL *ssl =
nullptr;
33335 std::lock_guard<std::mutex> guard(ctx_mutex);
33336 ssl = SSL_new(ctx);
33340 set_nonblocking(sock,
true);
33341 auto bio = BIO_new_socket(
static_cast<int>(sock), BIO_NOCLOSE);
33342 BIO_set_nbio(bio, 1);
33343 SSL_set_bio(ssl, bio, bio);
33345 if (!setup(ssl) || SSL_connect_or_accept(ssl) != 1) {
33348 std::lock_guard<std::mutex> guard(ctx_mutex);
33351 set_nonblocking(sock,
false);
33354 BIO_set_nbio(bio, 0);
33355 set_nonblocking(sock,
false);
33361inline void ssl_delete(std::mutex &ctx_mutex, SSL *ssl,
33362 bool shutdown_gracefully) {
33367 if (shutdown_gracefully) { SSL_shutdown(ssl); }
33369 std::lock_guard<std::mutex> guard(ctx_mutex);
33373template <
typename U>
33374bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl,
33375 U ssl_connect_or_accept,
33376 time_t timeout_sec,
33377 time_t timeout_usec) {
33379 while ((res = ssl_connect_or_accept(ssl)) != 1) {
33380 auto err = SSL_get_error(ssl, res);
33382 case SSL_ERROR_WANT_READ:
33383 if (select_read(sock, timeout_sec, timeout_usec) > 0) {
continue; }
33385 case SSL_ERROR_WANT_WRITE:
33386 if (select_write(sock, timeout_sec, timeout_usec) > 0) {
continue; }
33395template <
typename T>
33396inline bool process_server_socket_ssl(
33397 const std::atomic<socket_t> &svr_sock, SSL *ssl, socket_t sock,
33398 size_t keep_alive_max_count, time_t keep_alive_timeout_sec,
33399 time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec,
33400 time_t write_timeout_usec, T callback) {
33401 return process_server_socket_core(
33402 svr_sock, sock, keep_alive_max_count, keep_alive_timeout_sec,
33403 [&](
bool close_connection,
bool &connection_closed) {
33404 SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
33405 write_timeout_sec, write_timeout_usec);
33406 return callback(strm, close_connection, connection_closed);
33410template <
typename T>
33412process_client_socket_ssl(SSL *ssl, socket_t sock, time_t read_timeout_sec,
33413 time_t read_timeout_usec, time_t write_timeout_sec,
33414 time_t write_timeout_usec, T callback) {
33415 SSLSocketStream strm(sock, ssl, read_timeout_sec, read_timeout_usec,
33416 write_timeout_sec, write_timeout_usec);
33417 return callback(strm);
33424 OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
33429inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl,
33430 time_t read_timeout_sec,
33431 time_t read_timeout_usec,
33432 time_t write_timeout_sec,
33433 time_t write_timeout_usec)
33434 : sock_(sock), ssl_(ssl), read_timeout_sec_(read_timeout_sec),
33435 read_timeout_usec_(read_timeout_usec),
33436 write_timeout_sec_(write_timeout_sec),
33437 write_timeout_usec_(write_timeout_usec) {
33438 SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY);
33441inline SSLSocketStream::~SSLSocketStream() =
default;
33443inline bool SSLSocketStream::is_readable()
const {
33444 return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0;
33447inline bool SSLSocketStream::is_writable()
const {
33448 return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 &&
33449 is_socket_alive(sock_);
33452inline ssize_t SSLSocketStream::read(
char *ptr,
size_t size) {
33453 if (SSL_pending(ssl_) > 0) {
33454 return SSL_read(ssl_, ptr,
static_cast<int>(size));
33455 }
else if (is_readable()) {
33456 auto ret = SSL_read(ssl_, ptr,
static_cast<int>(size));
33458 auto err = SSL_get_error(ssl_, ret);
33461 while (--n >= 0 && (err == SSL_ERROR_WANT_READ ||
33462 (err == SSL_ERROR_SYSCALL &&
33463 WSAGetLastError() == WSAETIMEDOUT))) {
33465 while (--n >= 0 && err == SSL_ERROR_WANT_READ) {
33467 if (SSL_pending(ssl_) > 0) {
33468 return SSL_read(ssl_, ptr,
static_cast<int>(size));
33469 }
else if (is_readable()) {
33470 std::this_thread::sleep_for(std::chrono::milliseconds(1));
33471 ret = SSL_read(ssl_, ptr,
static_cast<int>(size));
33472 if (ret >= 0) {
return ret; }
33473 err = SSL_get_error(ssl_, ret);
33484inline ssize_t SSLSocketStream::write(
const char *ptr,
size_t size) {
33485 if (is_writable()) {
33486 auto handle_size =
static_cast<int>(
33487 std::min<size_t>(size, (std::numeric_limits<int>::max)()));
33489 auto ret = SSL_write(ssl_, ptr,
static_cast<int>(handle_size));
33491 auto err = SSL_get_error(ssl_, ret);
33494 while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE ||
33495 (err == SSL_ERROR_SYSCALL &&
33496 WSAGetLastError() == WSAETIMEDOUT))) {
33498 while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) {
33500 if (is_writable()) {
33501 std::this_thread::sleep_for(std::chrono::milliseconds(1));
33502 ret = SSL_write(ssl_, ptr,
static_cast<int>(handle_size));
33503 if (ret >= 0) {
return ret; }
33504 err = SSL_get_error(ssl_, ret);
33515inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip,
33517 detail::get_remote_ip_and_port(sock_, ip, port);
33520inline void SSLSocketStream::get_local_ip_and_port(std::string &ip,
33522 detail::get_local_ip_and_port(sock_, ip, port);
33525inline socket_t SSLSocketStream::socket()
const {
return sock_; }
33527static SSLInit sslinit_;
33532inline SSLServer::SSLServer(
const char *cert_path,
const char *private_key_path,
33533 const char *client_ca_cert_file_path,
33534 const char *client_ca_cert_dir_path,
33535 const char *private_key_password) {
33536 ctx_ = SSL_CTX_new(TLS_server_method());
33539 SSL_CTX_set_options(ctx_,
33540 SSL_OP_NO_COMPRESSION |
33541 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
33543 SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION);
33545 if (private_key_password !=
nullptr && (private_key_password[0] !=
'\0')) {
33546 SSL_CTX_set_default_passwd_cb_userdata(
33548 reinterpret_cast<void *
>(
const_cast<char *
>(private_key_password)));
33551 if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 ||
33552 SSL_CTX_use_PrivateKey_file(ctx_, private_key_path, SSL_FILETYPE_PEM) !=
33554 SSL_CTX_free(ctx_);
33556 }
else if (client_ca_cert_file_path || client_ca_cert_dir_path) {
33557 SSL_CTX_load_verify_locations(ctx_, client_ca_cert_file_path,
33558 client_ca_cert_dir_path);
33560 SSL_CTX_set_verify(
33561 ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
nullptr);
33566inline SSLServer::SSLServer(X509 *cert, EVP_PKEY *private_key,
33567 X509_STORE *client_ca_cert_store) {
33568 ctx_ = SSL_CTX_new(TLS_server_method());
33571 SSL_CTX_set_options(ctx_,
33572 SSL_OP_NO_COMPRESSION |
33573 SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
33575 SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION);
33577 if (SSL_CTX_use_certificate(ctx_, cert) != 1 ||
33578 SSL_CTX_use_PrivateKey(ctx_, private_key) != 1) {
33579 SSL_CTX_free(ctx_);
33581 }
else if (client_ca_cert_store) {
33582 SSL_CTX_set_cert_store(ctx_, client_ca_cert_store);
33584 SSL_CTX_set_verify(
33585 ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
nullptr);
33590inline SSLServer::SSLServer(
33591 const std::function<
bool(SSL_CTX &ssl_ctx)> &setup_ssl_ctx_callback) {
33592 ctx_ = SSL_CTX_new(TLS_method());
33594 if (!setup_ssl_ctx_callback(*ctx_)) {
33595 SSL_CTX_free(ctx_);
33601inline SSLServer::~SSLServer() {
33602 if (ctx_) { SSL_CTX_free(ctx_); }
33605inline bool SSLServer::is_valid()
const {
return ctx_; }
33607inline SSL_CTX *SSLServer::ssl_context()
const {
return ctx_; }
33609inline bool SSLServer::process_and_close_socket(socket_t sock) {
33610 auto ssl = detail::ssl_new(
33611 sock, ctx_, ctx_mutex_,
33613 return detail::ssl_connect_or_accept_nonblocking(
33614 sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_);
33616 [](SSL * ) {
return true; });
33620 ret = detail::process_server_socket_ssl(
33621 svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_,
33622 read_timeout_sec_, read_timeout_usec_, write_timeout_sec_,
33623 write_timeout_usec_,
33624 [
this, ssl](Stream &strm,
bool close_connection,
33625 bool &connection_closed) {
33626 return process_request(strm, close_connection, connection_closed,
33627 [&](Request &req) { req.ssl = ssl; });
33632 const bool shutdown_gracefully = ret;
33633 detail::ssl_delete(ctx_mutex_, ssl, shutdown_gracefully);
33636 detail::shutdown_socket(sock);
33637 detail::close_socket(sock);
33642inline SSLClient::SSLClient(
const std::string &host)
33643 : SSLClient(host, 443, std::
string(), std::
string()) {}
33645inline SSLClient::SSLClient(
const std::string &host,
int port)
33646 : SSLClient(host, port, std::
string(), std::
string()) {}
33648inline SSLClient::SSLClient(
const std::string &host,
int port,
33649 const std::string &client_cert_path,
33650 const std::string &client_key_path,
33651 const std::string &private_key_password)
33652 : ClientImpl(host, port, client_cert_path, client_key_path) {
33653 ctx_ = SSL_CTX_new(TLS_client_method());
33655 detail::split(&host_[0], &host_[host_.size()],
'.',
33656 [&](
const char *b,
const char *e) {
33657 host_components_.emplace_back(b, e);
33660 if (!client_cert_path.empty() && !client_key_path.empty()) {
33661 if (!private_key_password.empty()) {
33662 SSL_CTX_set_default_passwd_cb_userdata(
33663 ctx_,
reinterpret_cast<void *
>(
33664 const_cast<char *
>(private_key_password.c_str())));
33667 if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(),
33668 SSL_FILETYPE_PEM) != 1 ||
33669 SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(),
33670 SSL_FILETYPE_PEM) != 1) {
33671 SSL_CTX_free(ctx_);
33677inline SSLClient::SSLClient(
const std::string &host,
int port,
33678 X509 *client_cert, EVP_PKEY *client_key,
33679 const std::string &private_key_password)
33680 : ClientImpl(host, port) {
33681 ctx_ = SSL_CTX_new(TLS_client_method());
33683 detail::split(&host_[0], &host_[host_.size()],
'.',
33684 [&](
const char *b,
const char *e) {
33685 host_components_.emplace_back(b, e);
33688 if (client_cert !=
nullptr && client_key !=
nullptr) {
33689 if (!private_key_password.empty()) {
33690 SSL_CTX_set_default_passwd_cb_userdata(
33691 ctx_,
reinterpret_cast<void *
>(
33692 const_cast<char *
>(private_key_password.c_str())));
33695 if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 ||
33696 SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) {
33697 SSL_CTX_free(ctx_);
33703inline SSLClient::~SSLClient() {
33704 if (ctx_) { SSL_CTX_free(ctx_); }
33708 shutdown_ssl_impl(socket_,
true);
33711inline bool SSLClient::is_valid()
const {
return ctx_; }
33713inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) {
33714 if (ca_cert_store) {
33716 if (SSL_CTX_get_cert_store(ctx_) != ca_cert_store) {
33718 SSL_CTX_set_cert_store(ctx_, ca_cert_store);
33721 X509_STORE_free(ca_cert_store);
33726inline void SSLClient::load_ca_cert_store(
const char *ca_cert,
33727 std::size_t size) {
33728 set_ca_cert_store(ClientImpl::create_ca_cert_store(ca_cert, size));
33731inline long SSLClient::get_openssl_verify_result()
const {
33732 return verify_result_;
33735inline SSL_CTX *SSLClient::ssl_context()
const {
return ctx_; }
33737inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) {
33738 return is_valid() && ClientImpl::create_and_connect_socket(socket, error);
33742inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res,
33743 bool &success, Error &error) {
33745 Response proxy_res;
33746 if (!detail::process_client_socket(
33747 socket.sock, read_timeout_sec_, read_timeout_usec_,
33748 write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) {
33750 req2.method =
"CONNECT";
33751 req2.path = host_and_port_;
33752 return process_request(strm, req2, proxy_res, false, error);
33756 shutdown_ssl(socket,
true);
33757 shutdown_socket(socket);
33758 close_socket(socket);
33763 if (proxy_res.status == StatusCode::ProxyAuthenticationRequired_407) {
33764 if (!proxy_digest_auth_username_.empty() &&
33765 !proxy_digest_auth_password_.empty()) {
33766 std::map<std::string, std::string> auth;
33767 if (detail::parse_www_authenticate(proxy_res, auth,
true)) {
33768 proxy_res = Response();
33769 if (!detail::process_client_socket(
33770 socket.sock, read_timeout_sec_, read_timeout_usec_,
33771 write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) {
33773 req3.method =
"CONNECT";
33774 req3.path = host_and_port_;
33775 req3.headers.insert(detail::make_digest_authentication_header(
33776 req3, auth, 1, detail::random_string(10),
33777 proxy_digest_auth_username_, proxy_digest_auth_password_,
33779 return process_request(strm, req3, proxy_res, false, error);
33783 shutdown_ssl(socket,
true);
33784 shutdown_socket(socket);
33785 close_socket(socket);
33796 if (proxy_res.status != StatusCode::OK_200) {
33797 error = Error::ProxyConnection;
33798 res = std::move(proxy_res);
33801 shutdown_ssl(socket,
true);
33802 shutdown_socket(socket);
33803 close_socket(socket);
33810inline bool SSLClient::load_certs() {
33813 std::call_once(initialize_cert_, [&]() {
33814 std::lock_guard<std::mutex> guard(ctx_mutex_);
33815 if (!ca_cert_file_path_.empty()) {
33816 if (!SSL_CTX_load_verify_locations(ctx_, ca_cert_file_path_.c_str(),
33820 }
else if (!ca_cert_dir_path_.empty()) {
33821 if (!SSL_CTX_load_verify_locations(ctx_,
nullptr,
33822 ca_cert_dir_path_.c_str())) {
33826 auto loaded =
false;
33829 detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_));
33830#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__)
33832 loaded = detail::load_system_certs_on_macos(SSL_CTX_get_cert_store(ctx_));
33835 if (!loaded) { SSL_CTX_set_default_verify_paths(ctx_); }
33842inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) {
33843 auto ssl = detail::ssl_new(
33844 socket.sock, ctx_, ctx_mutex_,
33846 if (server_certificate_verification_) {
33847 if (!load_certs()) {
33848 error = Error::SSLLoadingCerts;
33851 SSL_set_verify(ssl2, SSL_VERIFY_NONE, nullptr);
33854 if (!detail::ssl_connect_or_accept_nonblocking(
33855 socket.sock, ssl2, SSL_connect, connection_timeout_sec_,
33856 connection_timeout_usec_)) {
33857 error = Error::SSLConnection;
33861 if (server_certificate_verification_) {
33862 verify_result_ = SSL_get_verify_result(ssl2);
33864 if (verify_result_ != X509_V_OK) {
33865 error = Error::SSLServerVerification;
33869 auto server_cert = SSL_get1_peer_certificate(ssl2);
33871 if (server_cert ==
nullptr) {
33872 error = Error::SSLServerVerification;
33876 if (!verify_host(server_cert)) {
33877 X509_free(server_cert);
33878 error = Error::SSLServerVerification;
33881 X509_free(server_cert);
33890 SSL_ctrl(ssl2, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name,
33891 static_cast<void *
>(
const_cast<char *
>(host_.c_str())));
33900 shutdown_socket(socket);
33901 close_socket(socket);
33905inline void SSLClient::shutdown_ssl(Socket &socket,
bool shutdown_gracefully) {
33906 shutdown_ssl_impl(socket, shutdown_gracefully);
33909inline void SSLClient::shutdown_ssl_impl(Socket &socket,
33910 bool shutdown_gracefully) {
33911 if (socket.sock == INVALID_SOCKET) {
33912 assert(socket.ssl ==
nullptr);
33916 detail::ssl_delete(ctx_mutex_, socket.ssl, shutdown_gracefully);
33917 socket.ssl =
nullptr;
33919 assert(socket.ssl ==
nullptr);
33923SSLClient::process_socket(
const Socket &socket,
33924 std::function<
bool(Stream &strm)> callback) {
33925 assert(socket.ssl);
33926 return detail::process_client_socket_ssl(
33927 socket.ssl, socket.sock, read_timeout_sec_, read_timeout_usec_,
33928 write_timeout_sec_, write_timeout_usec_, std::move(callback));
33931inline bool SSLClient::is_ssl()
const {
return true; }
33933inline bool SSLClient::verify_host(X509 *server_cert)
const {
33955 return verify_host_with_subject_alt_name(server_cert) ||
33956 verify_host_with_common_name(server_cert);
33960SSLClient::verify_host_with_subject_alt_name(X509 *server_cert)
const {
33963 auto type = GEN_DNS;
33965 struct in6_addr addr6 {};
33966 struct in_addr addr {};
33967 size_t addr_len = 0;
33970 if (inet_pton(AF_INET6, host_.c_str(), &addr6)) {
33972 addr_len =
sizeof(
struct in6_addr);
33973 }
else if (inet_pton(AF_INET, host_.c_str(), &addr)) {
33975 addr_len =
sizeof(
struct in_addr);
33979 auto alt_names =
static_cast<const struct stack_st_GENERAL_NAME *
>(
33980 X509_get_ext_d2i(server_cert, NID_subject_alt_name,
nullptr,
nullptr));
33983 auto dsn_matched =
false;
33984 auto ip_matched =
false;
33986 auto count = sk_GENERAL_NAME_num(alt_names);
33988 for (
decltype(count) i = 0; i < count && !dsn_matched; i++) {
33989 auto val = sk_GENERAL_NAME_value(alt_names, i);
33990 if (val->type == type) {
33992 reinterpret_cast<const char *
>(ASN1_STRING_get0_data(val->d.ia5));
33993 auto name_len =
static_cast<size_t>(ASN1_STRING_length(val->d.ia5));
33996 case GEN_DNS: dsn_matched = check_host_name(name, name_len);
break;
33999 if (!memcmp(&addr6, name, addr_len) ||
34000 !memcmp(&addr, name, addr_len)) {
34008 if (dsn_matched || ip_matched) { ret =
true; }
34011 GENERAL_NAMES_free(
const_cast<STACK_OF(GENERAL_NAME) *
>(
34012 reinterpret_cast<const STACK_OF(GENERAL_NAME) *
>(alt_names)));
34016inline bool SSLClient::verify_host_with_common_name(X509 *server_cert)
const {
34017 const auto subject_name = X509_get_subject_name(server_cert);
34019 if (subject_name !=
nullptr) {
34021 auto name_len = X509_NAME_get_text_by_NID(subject_name, NID_commonName,
34022 name,
sizeof(name));
34024 if (name_len != -1) {
34025 return check_host_name(name,
static_cast<size_t>(name_len));
34032inline bool SSLClient::check_host_name(
const char *pattern,
34033 size_t pattern_len)
const {
34034 if (host_.size() == pattern_len && host_ == pattern) {
return true; }
34038 std::vector<std::string> pattern_components;
34039 detail::split(&pattern[0], &pattern[pattern_len],
'.',
34040 [&](
const char *b,
const char *e) {
34041 pattern_components.emplace_back(b, e);
34044 if (host_components_.size() != pattern_components.size()) {
return false; }
34046 auto itr = pattern_components.begin();
34047 for (
const auto &h : host_components_) {
34049 if (p != h && p !=
"*") {
34050 auto partial_match = (p.size() > 0 && p[p.size() - 1] ==
'*' &&
34051 !p.compare(0, p.size() - 1, h));
34052 if (!partial_match) {
return false; }
34062inline Client::Client(
const std::string &scheme_host_port)
34063 : Client(scheme_host_port, std::
string(), std::
string()) {}
34065inline Client::Client(
const std::string &scheme_host_port,
34066 const std::string &client_cert_path,
34067 const std::string &client_key_path) {
34068 const static std::regex re(
34069 R
"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
34072 if (std::regex_match(scheme_host_port, m, re)) {
34073 auto scheme = m[1].str();
34075#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
34076 if (!scheme.empty() && (scheme !=
"http" && scheme !=
"https")) {
34078 if (!scheme.empty() && scheme !=
"http") {
34080#ifndef CPPHTTPLIB_NO_EXCEPTIONS
34081 std::string msg =
"'" + scheme +
"' scheme is not supported.";
34082 throw std::invalid_argument(msg);
34087 auto is_ssl = scheme ==
"https";
34089 auto host = m[2].str();
34090 if (host.empty()) { host = m[3].str(); }
34092 auto port_str = m[4].str();
34093 auto port = !port_str.empty() ? std::stoi(port_str) : (is_ssl ? 443 : 80);
34096#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
34097 cli_ = detail::make_unique<SSLClient>(host, port, client_cert_path,
34102 cli_ = detail::make_unique<ClientImpl>(host, port, client_cert_path,
34106 cli_ = detail::make_unique<ClientImpl>(scheme_host_port, 80,
34107 client_cert_path, client_key_path);
34111inline Client::Client(
const std::string &host,
int port)
34112 : cli_(
detail::make_unique<ClientImpl>(host, port)) {}
34114inline Client::Client(
const std::string &host,
int port,
34115 const std::string &client_cert_path,
34116 const std::string &client_key_path)
34117 : cli_(
detail::make_unique<ClientImpl>(host, port, client_cert_path,
34118 client_key_path)) {}
34120inline Client::~Client() =
default;
34122inline bool Client::is_valid()
const {
34123 return cli_ !=
nullptr && cli_->is_valid();
34126inline Result Client::Get(
const std::string &path) {
return cli_->Get(path); }
34127inline Result Client::Get(
const std::string &path,
const Headers &headers) {
34128 return cli_->Get(path, headers);
34130inline Result Client::Get(
const std::string &path, Progress progress) {
34131 return cli_->Get(path, std::move(progress));
34133inline Result Client::Get(
const std::string &path,
const Headers &headers,
34134 Progress progress) {
34135 return cli_->Get(path, headers, std::move(progress));
34137inline Result Client::Get(
const std::string &path,
34138 ContentReceiver content_receiver) {
34139 return cli_->Get(path, std::move(content_receiver));
34141inline Result Client::Get(
const std::string &path,
const Headers &headers,
34142 ContentReceiver content_receiver) {
34143 return cli_->Get(path, headers, std::move(content_receiver));
34145inline Result Client::Get(
const std::string &path,
34146 ContentReceiver content_receiver, Progress progress) {
34147 return cli_->Get(path, std::move(content_receiver), std::move(progress));
34149inline Result Client::Get(
const std::string &path,
const Headers &headers,
34150 ContentReceiver content_receiver, Progress progress) {
34151 return cli_->Get(path, headers, std::move(content_receiver),
34152 std::move(progress));
34154inline Result Client::Get(
const std::string &path,
34155 ResponseHandler response_handler,
34156 ContentReceiver content_receiver) {
34157 return cli_->Get(path, std::move(response_handler),
34158 std::move(content_receiver));
34160inline Result Client::Get(
const std::string &path,
const Headers &headers,
34161 ResponseHandler response_handler,
34162 ContentReceiver content_receiver) {
34163 return cli_->Get(path, headers, std::move(response_handler),
34164 std::move(content_receiver));
34166inline Result Client::Get(
const std::string &path,
34167 ResponseHandler response_handler,
34168 ContentReceiver content_receiver, Progress progress) {
34169 return cli_->Get(path, std::move(response_handler),
34170 std::move(content_receiver), std::move(progress));
34172inline Result Client::Get(
const std::string &path,
const Headers &headers,
34173 ResponseHandler response_handler,
34174 ContentReceiver content_receiver, Progress progress) {
34175 return cli_->Get(path, headers, std::move(response_handler),
34176 std::move(content_receiver), std::move(progress));
34178inline Result Client::Get(
const std::string &path,
const Params ¶ms,
34179 const Headers &headers, Progress progress) {
34180 return cli_->Get(path, params, headers, std::move(progress));
34182inline Result Client::Get(
const std::string &path,
const Params ¶ms,
34183 const Headers &headers,
34184 ContentReceiver content_receiver, Progress progress) {
34185 return cli_->Get(path, params, headers, std::move(content_receiver),
34186 std::move(progress));
34188inline Result Client::Get(
const std::string &path,
const Params ¶ms,
34189 const Headers &headers,
34190 ResponseHandler response_handler,
34191 ContentReceiver content_receiver, Progress progress) {
34192 return cli_->Get(path, params, headers, std::move(response_handler),
34193 std::move(content_receiver), std::move(progress));
34196inline Result Client::Head(
const std::string &path) {
return cli_->Head(path); }
34197inline Result Client::Head(
const std::string &path,
const Headers &headers) {
34198 return cli_->Head(path, headers);
34201inline Result Client::Post(
const std::string &path) {
return cli_->Post(path); }
34202inline Result Client::Post(
const std::string &path,
const Headers &headers) {
34203 return cli_->Post(path, headers);
34205inline Result Client::Post(
const std::string &path,
const char *body,
34206 size_t content_length,
34207 const std::string &content_type) {
34208 return cli_->Post(path, body, content_length, content_type);
34210inline Result Client::Post(
const std::string &path,
const Headers &headers,
34211 const char *body,
size_t content_length,
34212 const std::string &content_type) {
34213 return cli_->Post(path, headers, body, content_length, content_type);
34215inline Result Client::Post(
const std::string &path,
const Headers &headers,
34216 const char *body,
size_t content_length,
34217 const std::string &content_type, Progress progress) {
34218 return cli_->Post(path, headers, body, content_length, content_type,
34221inline Result Client::Post(
const std::string &path,
const std::string &body,
34222 const std::string &content_type) {
34223 return cli_->Post(path, body, content_type);
34226inline Result Client::Post(
const std::string &path,
const std::string &body,
34227 const std::string &content_type, ContentReceiver content_receiver) {
34228 return cli_->Post(path, body, content_type, std::move(content_receiver));
34231inline Result Client::Post(
const std::string &path,
const std::string &body,
34232 const std::string &content_type, Progress progress) {
34233 return cli_->Post(path, body, content_type, progress);
34235inline Result Client::Post(
const std::string &path,
const Headers &headers,
34236 const std::string &body,
34237 const std::string &content_type) {
34238 return cli_->Post(path, headers, body, content_type);
34241inline Result Client::Post(
const std::string &path,
const Headers &headers,
34242 const std::string &body,
34243 const std::string &content_type,
34244 ContentReceiver content_receiver) {
34245 return cli_->Post(path, headers, body, content_type, std::move(content_receiver));
34247inline Result Client::Post(
const std::string &path,
const Headers &headers,
34248 const std::string &body,
34249 const std::string &content_type, Progress progress) {
34250 return cli_->Post(path, headers, body, content_type, progress);
34252inline Result Client::Post(
const std::string &path,
size_t content_length,
34253 ContentProvider content_provider,
34254 const std::string &content_type) {
34255 return cli_->Post(path, content_length, std::move(content_provider),
34258inline Result Client::Post(
const std::string &path,
34259 ContentProviderWithoutLength content_provider,
34260 const std::string &content_type) {
34261 return cli_->Post(path, std::move(content_provider), content_type);
34263inline Result Client::Post(
const std::string &path,
const Headers &headers,
34264 size_t content_length,
34265 ContentProvider content_provider,
34266 const std::string &content_type) {
34267 return cli_->Post(path, headers, content_length, std::move(content_provider),
34270inline Result Client::Post(
const std::string &path,
const Headers &headers,
34271 ContentProviderWithoutLength content_provider,
34272 const std::string &content_type) {
34273 return cli_->Post(path, headers, std::move(content_provider), content_type);
34275inline Result Client::Post(
const std::string &path,
const Params ¶ms) {
34276 return cli_->Post(path, params);
34278inline Result Client::Post(
const std::string &path,
const Headers &headers,
34279 const Params ¶ms) {
34280 return cli_->Post(path, headers, params);
34282inline Result Client::Post(
const std::string &path,
const Headers &headers,
34283 const Params ¶ms, Progress progress) {
34284 return cli_->Post(path, headers, params, progress);
34286inline Result Client::Post(
const std::string &path,
34287 const MultipartFormDataItems &items) {
34288 return cli_->Post(path, items);
34290inline Result Client::Post(
const std::string &path,
const Headers &headers,
34291 const MultipartFormDataItems &items) {
34292 return cli_->Post(path, headers, items);
34294inline Result Client::Post(
const std::string &path,
const Headers &headers,
34295 const MultipartFormDataItems &items,
34296 const std::string &boundary) {
34297 return cli_->Post(path, headers, items, boundary);
34300Client::Post(
const std::string &path,
const Headers &headers,
34301 const MultipartFormDataItems &items,
34302 const MultipartFormDataProviderItems &provider_items) {
34303 return cli_->Post(path, headers, items, provider_items);
34305inline Result Client::Put(
const std::string &path) {
return cli_->Put(path); }
34306inline Result Client::Put(
const std::string &path,
const char *body,
34307 size_t content_length,
34308 const std::string &content_type) {
34309 return cli_->Put(path, body, content_length, content_type);
34311inline Result Client::Put(
const std::string &path,
const Headers &headers,
34312 const char *body,
size_t content_length,
34313 const std::string &content_type) {
34314 return cli_->Put(path, headers, body, content_length, content_type);
34316inline Result Client::Put(
const std::string &path,
const Headers &headers,
34317 const char *body,
size_t content_length,
34318 const std::string &content_type, Progress progress) {
34319 return cli_->Put(path, headers, body, content_length, content_type, progress);
34321inline Result Client::Put(
const std::string &path,
const std::string &body,
34322 const std::string &content_type) {
34323 return cli_->Put(path, body, content_type);
34325inline Result Client::Put(
const std::string &path,
const std::string &body,
34326 const std::string &content_type, Progress progress) {
34327 return cli_->Put(path, body, content_type, progress);
34329inline Result Client::Put(
const std::string &path,
const Headers &headers,
34330 const std::string &body,
34331 const std::string &content_type) {
34332 return cli_->Put(path, headers, body, content_type);
34334inline Result Client::Put(
const std::string &path,
const Headers &headers,
34335 const std::string &body,
34336 const std::string &content_type, Progress progress) {
34337 return cli_->Put(path, headers, body, content_type, progress);
34339inline Result Client::Put(
const std::string &path,
size_t content_length,
34340 ContentProvider content_provider,
34341 const std::string &content_type) {
34342 return cli_->Put(path, content_length, std::move(content_provider),
34345inline Result Client::Put(
const std::string &path,
34346 ContentProviderWithoutLength content_provider,
34347 const std::string &content_type) {
34348 return cli_->Put(path, std::move(content_provider), content_type);
34350inline Result Client::Put(
const std::string &path,
const Headers &headers,
34351 size_t content_length,
34352 ContentProvider content_provider,
34353 const std::string &content_type) {
34354 return cli_->Put(path, headers, content_length, std::move(content_provider),
34357inline Result Client::Put(
const std::string &path,
const Headers &headers,
34358 ContentProviderWithoutLength content_provider,
34359 const std::string &content_type) {
34360 return cli_->Put(path, headers, std::move(content_provider), content_type);
34362inline Result Client::Put(
const std::string &path,
const Params ¶ms) {
34363 return cli_->Put(path, params);
34365inline Result Client::Put(
const std::string &path,
const Headers &headers,
34366 const Params ¶ms) {
34367 return cli_->Put(path, headers, params);
34369inline Result Client::Put(
const std::string &path,
const Headers &headers,
34370 const Params ¶ms, Progress progress) {
34371 return cli_->Put(path, headers, params, progress);
34373inline Result Client::Put(
const std::string &path,
34374 const MultipartFormDataItems &items) {
34375 return cli_->Put(path, items);
34377inline Result Client::Put(
const std::string &path,
const Headers &headers,
34378 const MultipartFormDataItems &items) {
34379 return cli_->Put(path, headers, items);
34381inline Result Client::Put(
const std::string &path,
const Headers &headers,
34382 const MultipartFormDataItems &items,
34383 const std::string &boundary) {
34384 return cli_->Put(path, headers, items, boundary);
34387Client::Put(
const std::string &path,
const Headers &headers,
34388 const MultipartFormDataItems &items,
34389 const MultipartFormDataProviderItems &provider_items) {
34390 return cli_->Put(path, headers, items, provider_items);
34392inline Result Client::Patch(
const std::string &path) {
34393 return cli_->Patch(path);
34395inline Result Client::Patch(
const std::string &path,
const char *body,
34396 size_t content_length,
34397 const std::string &content_type) {
34398 return cli_->Patch(path, body, content_length, content_type);
34400inline Result Client::Patch(
const std::string &path,
const char *body,
34401 size_t content_length,
34402 const std::string &content_type, Progress progress) {
34403 return cli_->Patch(path, body, content_length, content_type, progress);
34405inline Result Client::Patch(
const std::string &path,
const Headers &headers,
34406 const char *body,
size_t content_length,
34407 const std::string &content_type) {
34408 return cli_->Patch(path, headers, body, content_length, content_type);
34410inline Result Client::Patch(
const std::string &path,
const Headers &headers,
34411 const char *body,
size_t content_length,
34412 const std::string &content_type, Progress progress) {
34413 return cli_->Patch(path, headers, body, content_length, content_type, progress);
34415inline Result Client::Patch(
const std::string &path,
const std::string &body,
34416 const std::string &content_type) {
34417 return cli_->Patch(path, body, content_type);
34419inline Result Client::Patch(
const std::string &path,
const std::string &body,
34420 const std::string &content_type, Progress progress) {
34421 return cli_->Patch(path, body, content_type, progress);
34423inline Result Client::Patch(
const std::string &path,
const Headers &headers,
34424 const std::string &body,
34425 const std::string &content_type) {
34426 return cli_->Patch(path, headers, body, content_type);
34428inline Result Client::Patch(
const std::string &path,
const Headers &headers,
34429 const std::string &body,
34430 const std::string &content_type, Progress progress) {
34431 return cli_->Patch(path, headers, body, content_type, progress);
34433inline Result Client::Patch(
const std::string &path,
size_t content_length,
34434 ContentProvider content_provider,
34435 const std::string &content_type) {
34436 return cli_->Patch(path, content_length, std::move(content_provider),
34439inline Result Client::Patch(
const std::string &path,
34440 ContentProviderWithoutLength content_provider,
34441 const std::string &content_type) {
34442 return cli_->Patch(path, std::move(content_provider), content_type);
34444inline Result Client::Patch(
const std::string &path,
const Headers &headers,
34445 size_t content_length,
34446 ContentProvider content_provider,
34447 const std::string &content_type) {
34448 return cli_->Patch(path, headers, content_length, std::move(content_provider),
34451inline Result Client::Patch(
const std::string &path,
const Headers &headers,
34452 ContentProviderWithoutLength content_provider,
34453 const std::string &content_type) {
34454 return cli_->Patch(path, headers, std::move(content_provider), content_type);
34456inline Result Client::Delete(
const std::string &path) {
34457 return cli_->Delete(path);
34459inline Result Client::Delete(
const std::string &path,
const Headers &headers) {
34460 return cli_->Delete(path, headers);
34462inline Result Client::Delete(
const std::string &path,
const char *body,
34463 size_t content_length,
34464 const std::string &content_type) {
34465 return cli_->Delete(path, body, content_length, content_type);
34467inline Result Client::Delete(
const std::string &path,
const char *body,
34468 size_t content_length,
34469 const std::string &content_type, Progress progress) {
34470 return cli_->Delete(path, body, content_length, content_type, progress);
34472inline Result Client::Delete(
const std::string &path,
const Headers &headers,
34473 const char *body,
size_t content_length,
34474 const std::string &content_type) {
34475 return cli_->Delete(path, headers, body, content_length, content_type);
34477inline Result Client::Delete(
const std::string &path,
const Headers &headers,
34478 const char *body,
size_t content_length,
34479 const std::string &content_type, Progress progress) {
34480 return cli_->Delete(path, headers, body, content_length, content_type, progress);
34482inline Result Client::Delete(
const std::string &path,
const std::string &body,
34483 const std::string &content_type) {
34484 return cli_->Delete(path, body, content_type);
34486inline Result Client::Delete(
const std::string &path,
const std::string &body,
34487 const std::string &content_type, Progress progress) {
34488 return cli_->Delete(path, body, content_type, progress);
34490inline Result Client::Delete(
const std::string &path,
const Headers &headers,
34491 const std::string &body,
34492 const std::string &content_type) {
34493 return cli_->Delete(path, headers, body, content_type);
34495inline Result Client::Delete(
const std::string &path,
const Headers &headers,
34496 const std::string &body,
34497 const std::string &content_type, Progress progress) {
34498 return cli_->Delete(path, headers, body, content_type, progress);
34500inline Result Client::Options(
const std::string &path) {
34501 return cli_->Options(path);
34503inline Result Client::Options(
const std::string &path,
const Headers &headers) {
34504 return cli_->Options(path, headers);
34507inline bool Client::send(Request &req, Response &res, Error &error) {
34508 return cli_->send(req, res, error);
34511inline Result Client::send(
const Request &req) {
return cli_->send(req); }
34513inline void Client::stop() { cli_->stop(); }
34515inline std::string Client::host()
const {
return cli_->host(); }
34517inline int Client::port()
const {
return cli_->port(); }
34519inline size_t Client::is_socket_open()
const {
return cli_->is_socket_open(); }
34521inline socket_t Client::socket()
const {
return cli_->socket(); }
34524Client::set_hostname_addr_map(std::map<std::string, std::string> addr_map) {
34525 cli_->set_hostname_addr_map(std::move(addr_map));
34528inline void Client::set_default_headers(Headers headers) {
34529 cli_->set_default_headers(std::move(headers));
34532inline void Client::set_header_writer(
34533 std::function<ssize_t(Stream &, Headers &)>
const &writer) {
34534 cli_->set_header_writer(writer);
34537inline void Client::set_address_family(
int family) {
34538 cli_->set_address_family(family);
34541inline void Client::set_tcp_nodelay(
bool on) { cli_->set_tcp_nodelay(on); }
34543inline void Client::set_socket_options(SocketOptions socket_options) {
34544 cli_->set_socket_options(std::move(socket_options));
34547inline void Client::set_connection_timeout(time_t sec, time_t usec) {
34548 cli_->set_connection_timeout(sec, usec);
34551inline void Client::set_read_timeout(time_t sec, time_t usec) {
34552 cli_->set_read_timeout(sec, usec);
34555inline void Client::set_write_timeout(time_t sec, time_t usec) {
34556 cli_->set_write_timeout(sec, usec);
34559inline void Client::set_basic_auth(
const std::string &username,
34560 const std::string &password) {
34561 cli_->set_basic_auth(username, password);
34563inline void Client::set_bearer_token_auth(
const std::string &token) {
34564 cli_->set_bearer_token_auth(token);
34566#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
34567inline void Client::set_digest_auth(
const std::string &username,
34568 const std::string &password) {
34569 cli_->set_digest_auth(username, password);
34573inline void Client::set_keep_alive(
bool on) { cli_->set_keep_alive(on); }
34574inline void Client::set_follow_location(
bool on) {
34575 cli_->set_follow_location(on);
34578inline void Client::set_url_encode(
bool on) { cli_->set_url_encode(on); }
34580inline void Client::set_compress(
bool on) { cli_->set_compress(on); }
34582inline void Client::set_decompress(
bool on) { cli_->set_decompress(on); }
34584inline void Client::set_interface(
const std::string &intf) {
34585 cli_->set_interface(intf);
34588inline void Client::set_proxy(
const std::string &host,
int port) {
34589 cli_->set_proxy(host, port);
34591inline void Client::set_proxy_basic_auth(
const std::string &username,
34592 const std::string &password) {
34593 cli_->set_proxy_basic_auth(username, password);
34595inline void Client::set_proxy_bearer_token_auth(
const std::string &token) {
34596 cli_->set_proxy_bearer_token_auth(token);
34598#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
34599inline void Client::set_proxy_digest_auth(
const std::string &username,
34600 const std::string &password) {
34601 cli_->set_proxy_digest_auth(username, password);
34605#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
34606inline void Client::enable_server_certificate_verification(
bool enabled) {
34607 cli_->enable_server_certificate_verification(enabled);
34611inline void Client::set_logger(Logger logger) {
34612 cli_->set_logger(std::move(logger));
34615#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
34616inline void Client::set_ca_cert_path(
const std::string &ca_cert_file_path,
34617 const std::string &ca_cert_dir_path) {
34618 cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path);
34621inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) {
34623 static_cast<SSLClient &
>(*cli_).set_ca_cert_store(ca_cert_store);
34625 cli_->set_ca_cert_store(ca_cert_store);
34629inline void Client::load_ca_cert_store(
const char *ca_cert, std::size_t size) {
34630 set_ca_cert_store(cli_->create_ca_cert_store(ca_cert, size));
34633inline long Client::get_openssl_verify_result()
const {
34635 return static_cast<SSLClient &
>(*cli_).get_openssl_verify_result();
34640inline SSL_CTX *Client::ssl_context()
const {
34641 if (is_ssl_) {
return static_cast<SSLClient &
>(*cli_).ssl_context(); }
34650#if defined(_WIN32) && defined(CPPHTTPLIB_USE_POLL)
34658#ifndef _MACARON_BASE64_H_
34659#define _MACARON_BASE64_H_
34692 static std::string Encode(
const std::string &data) {
34693 static constexpr char sEncodingTable[] = {
34694 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
34695 'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
34696 'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
34697 'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
34698 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'};
34700 size_t in_len = data.size();
34701 size_t out_len = 4 * ((in_len + 2) / 3);
34702 std::string ret(out_len,
'\0');
34704 char *p =
const_cast<char *
>(ret.c_str());
34706 for (i = 0; in_len > 2 && i < in_len - 2; i += 3) {
34707 *p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
34708 *p++ = sEncodingTable[((data[i] & 0x3) << 4) |
34709 ((int)(data[i + 1] & 0xF0) >> 4)];
34710 *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2) |
34711 ((int)(data[i + 2] & 0xC0) >> 6)];
34712 *p++ = sEncodingTable[data[i + 2] & 0x3F];
34715 *p++ = sEncodingTable[(data[i] >> 2) & 0x3F];
34716 if (i == (in_len - 1)) {
34717 *p++ = sEncodingTable[((data[i] & 0x3) << 4)];
34720 *p++ = sEncodingTable[((data[i] & 0x3) << 4) |
34721 ((int)(data[i + 1] & 0xF0) >> 4)];
34722 *p++ = sEncodingTable[((data[i + 1] & 0xF) << 2)];
34730 static std::string Decode(
const std::string &input, std::string &out) {
34731 static constexpr unsigned char kDecodingTable[] = {
34732 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34733 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34734 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57,
34735 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0, 1, 2, 3, 4, 5, 6,
34736 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
34737 25, 64, 64, 64, 64, 64, 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
34738 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64,
34739 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34740 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34741 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34742 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34743 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34744 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34745 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
34748 size_t in_len = input.size();
34749 if (in_len % 4 != 0)
34750 return "Input data size is not a multiple of 4";
34752 size_t out_len = in_len / 4 * 3;
34753 if (in_len >= 1 && input[in_len - 1] ==
'=')
34755 if (in_len >= 2 && input[in_len - 2] ==
'=')
34758 out.resize(out_len);
34760 for (
size_t i = 0, j = 0; i < in_len;) {
34761 uint32_t a = input[i] ==
'='
34763 : kDecodingTable[
static_cast<int>(input[i++])];
34764 uint32_t b = input[i] ==
'='
34766 : kDecodingTable[
static_cast<int>(input[i++])];
34767 uint32_t c = input[i] ==
'='
34769 : kDecodingTable[
static_cast<int>(input[i++])];
34770 uint32_t d = input[i] ==
'='
34772 : kDecodingTable[
static_cast<int>(input[i++])];
34775 (a << 3 * 6) + (b << 2 * 6) + (c << 1 * 6) + (d << 0 * 6);
34778 out[j++] = (triple >> 2 * 8) & 0xFF;
34780 out[j++] = (triple >> 1 * 8) & 0xFF;
34782 out[j++] = (triple >> 0 * 8) & 0xFF;
34859#include <functional>
34860#include <exception>
34861#include <initializer_list>
34866 using json = nlohmann::json;
34869 static bool use_exceptions =
true;
34870 static bool log_requests =
false;
34871 static bool log_replies =
false;
34873 static void allow_exceptions(
bool enable) {use_exceptions = enable;}
34874 static void show_requests(
bool enable) {log_requests = enable;}
34875 static void show_replies(
bool enable) {log_replies = enable;}
34877 enum class message_type { generation, chat, embedding };
34885 const char* what()
const noexcept override {
return message.c_str(); }
34892 image(
const std::string base64_sequence,
bool valid =
true)
34894 this->base64_sequence = base64_sequence; this->valid = valid;
34898 static image from_file(
const std::string& filepath)
34901 std::ifstream file(filepath, std::ios::binary);
34903 if (ollama::use_exceptions)
throw ollama::exception(
"Unable to open image file from path.");
34904 valid =
false;
return image(
"", valid);
34907 std::string file_contents((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
34909 return image(macaron::Base64::Encode(file_contents), valid);
34912 static image from_base64_string(
const std::string& base64_string)
34914 return image(base64_string);
34917 const std::string as_base64_string()
const
34919 return base64_sequence;
34922 bool is_valid(){
return valid;}
34924 operator std::string()
const {
return base64_sequence; }
34926 operator std::vector<ollama::image>()
const { std::vector<ollama::image>
images;
images.push_back(*
this);
return images; }
34927 operator std::vector<std::string>()
const { std::vector<std::string>
images;
images.push_back(*
this);
return images; }
34930 std::string base64_sequence;
34937 images(): std::vector<std::string>(0)
34941 images(
const std::initializer_list<ollama::image>& list) {
34943 this->push_back(value);
34947 std::vector<std::string> to_strings()
34949 std::vector<std::string> strings;
34950 for (
auto it = this->begin(); it != this->end(); ++it)
34951 strings.push_back(*it);
34961 options(): json() { this->emplace(
"options", nlohmann::json::object() ); }
34963 nlohmann::json& operator[](
const std::string& key)
34965 if ( !this->at(
"options").contains(key) ) this->at(
"options").emplace( key, nlohmann::json::object() );
34966 return this->at(
"options").at(key);
34968 nlohmann::json& operator[](
const char* key) {
return this->operator[](std::string(key)); };
34970 const nlohmann::json& operator[](
const std::string& key)
const {
return this->at(
"options").at(key); }
34971 const nlohmann::json& operator[](
const char* key)
const {
return this->operator[](std::string(key)); };
34977 message(
const std::string& role,
const std::string& content,
const std::vector<ollama::image>&
images): json() { (*this)[
"role"] = role; (*this)[
"content"] = content; (*this)[
"images"] =
images; }
34978 message(
const std::string& role,
const std::string& content): json() { (*this)[
"role"] = role; (*this)[
"content"] = content; }
34982 std::string as_json_string()
const {
return this->dump(); }
34984 operator std::string()
const {
return this->as_json_string(); }
34991 messages(): std::vector<message>(0) {}
34994 messages(
const std::initializer_list<message>& list) {
34996 this->push_back(value);
35000 const std::vector<std::string> to_strings()
const
35002 std::vector<std::string> strings;
35003 for (
auto it = this->begin(); it != this->end(); ++it)
35004 strings.push_back(*it);
35009 const std::vector<json> to_json()
const
35011 std::vector<json> output;
35012 for (
auto it = this->begin(); it != this->end(); ++it)
35013 output.push_back(*it);
35017 operator std::vector<json>()
const {
return std::vector<json>();}
35018 operator std::vector<std::string>()
const {
return this->to_strings(); }
35027 request(
const std::string& model,
const std::string& prompt,
const json&
options=
nullptr,
bool stream=
false,
const std::vector<std::string>&
images=std::vector<std::string>()):
request()
35029 (*this)[
"model"] = model;
35030 (*this)[
"prompt"] = prompt;
35031 (*this)[
"stream"] = stream;
35036 type = message_type::generation;
35042 (*this)[
"model"] = model;
35043 (*this)[
"messages"] =
messages.to_json();
35044 (*this)[
"stream"] = stream;
35048 (*this)[
"keep_alive"] = keep_alive_duration;
35049 type = message_type::chat;
35053 request(
const std::string& model,
const ollama::message&
message,
const json&
options=
nullptr,
bool stream=
false,
const std::string& format=
"json",
const std::string& keep_alive_duration=
"5m") :
request(model,
messages(
message),
options, stream, format, keep_alive_duration ){}
35060 static ollama::request from_embedding(
const std::string& model,
const std::string& input,
const json&
options=
nullptr,
bool truncate=
true,
const std::string& keep_alive_duration=
"5m")
35067 request[
"truncate"] = truncate;
35068 request[
"keep_alive"] = keep_alive_duration;
35073 const message_type& get_type()
const {
return type; }
35084 response(
const std::string& json_string, message_type type=message_type::generation): type(type)
35086 this->json_string = json_string;
35089 json_data = json::parse(json_string);
35091 if (type==message_type::generation && json_data.contains(
"response")) simple_string=json_data[
"response"].get<std::string>();
35093 if (type==message_type::embedding && json_data.contains(
"embeddings")) simple_string=json_data[
"embeddings"].get<std::string>();
35095 if (type==message_type::chat && json_data.contains(
"message")) simple_string=json_data[
"message"][
"content"].get<std::string>();
35097 if ( json_data.contains(
"error") ) error_string =json_data[
"error"].get<std::string>();
35099 catch(...) {
if (ollama::use_exceptions)
throw ollama::invalid_json_exception(
"Unable to parse JSON string:"+this->json_string); valid =
false; }
35102 response() {json_string =
""; valid =
false;}
35105 bool is_valid()
const {
return valid;};
35107 const std::string& as_json_string()
const
35109 return json_string;
35112 const json& as_json()
const
35117 const std::string& as_simple_string()
const
35119 return simple_string;
35122 bool has_error()
const
35124 if ( json_data.contains(
"error") )
return true;
35128 const std::string& get_error()
const
35130 return error_string;
35135 const message_type& get_type()
const
35141 operator std::__cxx11::basic_string<char>()
const {
return this->as_simple_string(); }
35147 std::string json_string;
35148 std::string simple_string;
35149 std::string error_string;
35160 using json = nlohmann::json;
35164 Ollama(
const std::string& url)
35166 this->server_url = url;
35168 this->setReadTimeout(120);
35172 ~Ollama() {
delete this->cli; }
35174 ollama::response generate(
const std::string& model,
const std::string& prompt,
const ollama::response& context,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35177 if ( context.as_json().contains(
"context") ) request[
"context"] = context.as_json()[
"context"];
35178 return generate(request);
35181 ollama::response generate(
const std::string& model,
const std::string& prompt,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35184 return generate(request);
35192 request[
"stream"] =
false;
35193 std::string request_string = request.dump();
35194 if (ollama::log_requests) std::cout << request_string << std::endl;
35196 if (
auto res = this->cli->Post(
"/api/generate",request_string,
"application/json"))
35198 if (ollama::log_replies) std::cout << res->body << std::endl;
35201 if ( response.has_error() ) {
if (ollama::use_exceptions)
throw ollama::exception(
"Ollama response returned error: "+response.get_error() ); }
35206 if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server "+this->server_url+
". Error was: "+httplib::to_string( res.error() ));
35212 bool generate(
const std::string& model,
const std::string& prompt,
ollama::response& context, std::function<
bool(
const ollama::response&)> on_receive_token,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35215 if ( context.as_json().contains(
"context") ) request[
"context"] = context.as_json()[
"context"];
35216 return generate(request, on_receive_token);
35219 bool generate(
const std::string& model,
const std::string& prompt, std::function<
bool(
const ollama::response&)> on_receive_token,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35222 return generate(request, on_receive_token);
35229 request[
"stream"] =
true;
35231 std::string request_string = request.dump();
35232 if (ollama::log_requests) std::cout << request_string << std::endl;
35234 std::shared_ptr<std::vector<std::string>> partial_responses = std::make_shared<std::vector<std::string>>();
35236 auto stream_callback = [on_receive_token, partial_responses](
const char *data,
size_t data_length)->
bool{
35238 std::string message(data, data_length);
35239 bool continue_stream =
true;
35241 if (ollama::log_replies) std::cout << message << std::endl;
35244 partial_responses->push_back(message);
35245 std::string total_response = std::accumulate(partial_responses->begin(), partial_responses->end(), std::string(
""));
35247 partial_responses->clear();
35248 continue_stream = on_receive_token(response);
35252 return continue_stream;
35255 if (
auto res = this->cli->Post(
"/api/generate", request_string,
"application/json", stream_callback)) {
return true; }
35256 else if (res.error()==httplib::Error::Canceled) {
return true; }
35257 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response from server returned at URL "+this->server_url+
" Error: "+httplib::to_string( res.error() ) ); }
35262 ollama::response chat(
const std::string& model,
const ollama::messages& messages, json options=
nullptr,
const std::string& format=
"json",
const std::string& keep_alive_duration=
"5m")
35264 ollama::request request(model, messages, options,
false, format, keep_alive_duration);
35265 return chat(request);
35274 request[
"stream"] =
false;
35275 std::string request_string = request.dump();
35276 if (ollama::log_requests) std::cout << request_string << std::endl;
35278 if (
auto res = this->cli->Post(
"/api/chat",request_string,
"application/json"))
35280 if (ollama::log_replies) std::cout << res->body << std::endl;
35283 if ( response.has_error() ) {
if (ollama::use_exceptions)
throw ollama::exception(
"Ollama response returned error: "+response.get_error() ); }
35288 if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server "+this->server_url+
". Error was: "+httplib::to_string( res.error() ));
35294 bool chat(
const std::string& model,
const ollama::messages& messages, std::function<
bool(
const ollama::response&)> on_receive_token,
const json& options=
nullptr,
const std::string& format=
"json",
const std::string& keep_alive_duration=
"5m")
35296 ollama::request request(model, messages, options,
true, format, keep_alive_duration);
35297 return chat(request, on_receive_token);
35304 request[
"stream"] =
true;
35306 std::string request_string = request.dump();
35307 if (ollama::log_requests) std::cout << request_string << std::endl;
35309 std::shared_ptr<std::vector<std::string>> partial_responses = std::make_shared<std::vector<std::string>>();
35311 auto stream_callback = [on_receive_token, partial_responses](
const char *data,
size_t data_length)->
bool{
35313 std::string message(data, data_length);
35314 bool continue_stream =
true;
35316 if (ollama::log_replies) std::cout << message << std::endl;
35319 partial_responses->push_back(message);
35320 std::string total_response = std::accumulate(partial_responses->begin(), partial_responses->end(), std::string(
""));
35322 partial_responses->clear();
35324 if ( response.has_error() ) {
if (ollama::use_exceptions)
throw ollama::exception(
"Ollama response returned error: "+response.get_error() ); }
35325 continue_stream = on_receive_token(response);
35329 return continue_stream;
35332 if (
auto res = this->cli->Post(
"/api/chat", request_string,
"application/json", stream_callback)) {
return true; }
35333 else if (res.error()==httplib::Error::Canceled) {
return true; }
35334 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response from server returned at URL"+this->server_url+
" Error: "+httplib::to_string( res.error() ) ); }
35339 bool create_model(
const std::string& modelName,
const std::string& modelFile,
bool loadFromFile=
true)
35344 request[
"name"] = modelName;
35349 std::ifstream file(modelFile, std::ios::binary);
35352 if (!file.is_open()) {
35353 if (ollama::use_exceptions)
throw ollama::exception(
"Failed to open file "+modelFile);
35358 std::string file_contents((std::istreambuf_iterator<char>(file)),
35359 std::istreambuf_iterator<char>());
35361 request[
"modelFile"] = file_contents;
35363 else request[
"modelFile"] = modelFile;
35365 std::string request_string = request.dump();
35366 if (ollama::log_requests) std::cout << request_string << std::endl;
35368 std::string response;
35370 if (
auto res = this->cli->Post(
"/api/create",request_string,
"application/json"))
35372 if (ollama::log_replies) std::cout << res->body << std::endl;
35374 json chunk = json::parse(res->body);
35375 if (chunk[
"status"]==
"success")
return true;
35379 if (ollama::use_exceptions)
throw ollama::exception(
"No response returned: "+httplib::to_string( res.error() ) );
35386 bool load_model(
const std::string& model)
35389 request[
"model"] = model;
35390 std::string request_string = request.dump();
35391 if (ollama::log_requests) std::cout << request_string << std::endl;
35394 if (
auto res = this->cli->Post(
"/api/generate", request_string,
"application/json"))
35396 if (ollama::log_replies) std::cout << res->body << std::endl;
35397 json response = json::parse(res->body);
35398 return response[
"done"];
35402 if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when loading model: "+httplib::to_string( res.error() ) );
35411 auto res = cli->Get(
"/");
35412 if (res)
if (res->body==
"Ollama is running")
return true;
35416 json list_model_json()
35419 if (
auto res = cli->Get(
"/api/tags"))
35421 if (ollama::log_replies) std::cout << res->body << std::endl;
35422 models = json::parse(res->body);
35424 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when querying model list: "+httplib::to_string( res.error() ) );}
35429 std::vector<std::string> list_models()
35431 std::vector<std::string> models;
35433 json json_response = list_model_json();
35435 for (
auto& model: json_response[
"models"])
35437 models.push_back(model[
"name"]);
35443 json running_model_json()
35446 if (
auto res = cli->Get(
"/api/ps"))
35448 if (ollama::log_replies) std::cout << res->body << std::endl;
35449 models = json::parse(res->body);
35451 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when querying running models: "+httplib::to_string( res.error() ) );}
35456 std::vector<std::string> list_running_models()
35458 std::vector<std::string> models;
35460 json json_response = running_model_json();
35462 for (
auto& model: json_response[
"models"])
35464 models.push_back(model[
"name"]);
35470 bool blob_exists(
const std::string& digest)
35472 if (
auto res = cli->Head(
"/api/blobs/"+digest))
35474 if (res->status==httplib::StatusCode::OK_200)
return true;
35475 if (res->status==httplib::StatusCode::NotFound_404)
return false;
35477 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when checking if blob exists: "+httplib::to_string( res.error() ) );}
35482 bool create_blob(
const std::string& digest)
35484 if (
auto res = cli->Post(
"/api/blobs/"+digest))
35486 if (res->status==httplib::StatusCode::Created_201)
return true;
35487 if (res->status==httplib::StatusCode::BadRequest_400) {
if (ollama::use_exceptions)
throw ollama::exception(
"Received bad request (Code 400) from Ollama server when creating blob."); }
35489 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when creating blob: "+httplib::to_string( res.error() ) );}
35495 json show_model_info(
const std::string& model,
bool verbose=
false)
35497 json request, response;
35498 request[
"name"] = model;
35499 if (verbose) request[
"verbose"] =
true;
35501 std::string request_string = request.dump();
35502 if (ollama::log_requests) std::cout << request_string << std::endl;
35504 if (
auto res = cli->Post(
"/api/show", request_string,
"application/json"))
35506 if (ollama::log_replies) std::cout <<
"Reply was " << res->body << std::endl;
35509 response = json::parse(res->body);
35512 {
if (ollama::use_exceptions)
throw ollama::exception(
"Received bad response from Ollama server when querying model info."); }
35514 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when querying model info: "+httplib::to_string( res.error() ) );}
35519 bool copy_model(
const std::string& source_model,
const std::string& dest_model)
35522 request[
"source"] = source_model;
35523 request[
"destination"] = dest_model;
35525 std::string request_string = request.dump();
35526 if (ollama::log_requests) std::cout << request_string << std::endl;
35528 if (
auto res = cli->Post(
"/api/copy", request_string,
"application/json"))
35530 if (res->status==httplib::StatusCode::OK_200)
return true;
35531 if (res->status==httplib::StatusCode::NotFound_404) {
if (ollama::use_exceptions)
throw ollama::exception(
"Source model not found when copying model (Code 404)."); }
35533 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when copying model: "+httplib::to_string( res.error() ) );}
35538 bool delete_model(
const std::string& model)
35541 request[
"name"] = model;
35543 std::string request_string = request.dump();
35544 if (ollama::log_requests) std::cout << request_string << std::endl;
35546 if (
auto res = cli->Delete(
"/api/delete", request_string,
"application/json"))
35548 if (res->status==httplib::StatusCode::OK_200)
return true;
35549 if (res->status==httplib::StatusCode::NotFound_404) {
if (ollama::use_exceptions)
throw ollama::exception(
"Model not found when trying to delete (Code 404)."); }
35551 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when deleting model: "+httplib::to_string( res.error() ) );}
35556 bool pull_model(
const std::string& model,
bool allow_insecure =
false)
35558 json request, response;
35559 request[
"name"] = model;
35560 request[
"insecure"] = allow_insecure;
35561 request[
"stream"] =
false;
35563 std::string request_string = request.dump();
35564 if (ollama::log_requests) std::cout << request_string << std::endl;
35566 if (
auto res = cli->Post(
"/api/pull", request_string,
"application/json"))
35568 if (res->status==httplib::StatusCode::OK_200)
return true;
35569 if (res->status==httplib::StatusCode::NotFound_404) {
if (ollama::use_exceptions)
throw ollama::exception(
"Model not found when trying to pull (Code 404).");
return false; }
35571 response = json::parse(res->body);
35572 if ( response.contains(
"error") ) {
if (ollama::use_exceptions)
throw ollama::exception(
"Error returned from ollama when pulling model: "+response[
"error"].get<std::string>() );
return false; }
35574 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when pulling model: "+httplib::to_string( res.error() ) );}
35579 bool push_model(
const std::string& model,
bool allow_insecure =
false)
35581 json request, response;
35582 request[
"name"] = model;
35583 request[
"insecure"] = allow_insecure;
35584 request[
"stream"] =
false;
35586 std::string request_string = request.dump();
35587 if (ollama::log_requests) std::cout << request_string << std::endl;
35589 if (
auto res = cli->Post(
"/api/push", request_string,
"application/json"))
35591 if (res->status==httplib::StatusCode::OK_200)
return true;
35592 if (res->status==httplib::StatusCode::NotFound_404) {
if (ollama::use_exceptions)
throw ollama::exception(
"Model not found when trying to push (Code 404).");
return false; }
35594 response = json::parse(res->body);
35595 if ( response.contains(
"error") ) {
if (ollama::use_exceptions)
throw ollama::exception(
"Error returned from ollama when pushing model: "+response[
"error"].get<std::string>() );
return false; }
35597 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when pushing model: "+httplib::to_string( res.error() ) );}
35602 ollama::response generate_embeddings(
const std::string& model,
const std::string& input,
const json& options=
nullptr,
bool truncate =
true,
const std::string& keep_alive_duration=
"5m")
35604 ollama::request request = ollama::request::from_embedding(model, input, options, truncate, keep_alive_duration);
35605 return generate_embeddings(request);
35613 std::string request_string = request.dump();
35614 if (ollama::log_requests) std::cout << request_string << std::endl;
35616 if (
auto res = cli->Post(
"/api/embed", request_string,
"application/json"))
35618 if (ollama::log_replies) std::cout << res->body << std::endl;
35621 if (res->status==httplib::StatusCode::OK_200) {response =
ollama::response(res->body);
return response; };
35622 if (res->status==httplib::StatusCode::NotFound_404) {
if (ollama::use_exceptions)
throw ollama::exception(
"Model not found when trying to push (Code 404)."); }
35624 if ( response.has_error() ) {
if (ollama::use_exceptions)
throw ollama::exception(
"Error returned from ollama when generating embeddings: "+response.get_error() ); }
35626 else {
if (ollama::use_exceptions)
throw ollama::exception(
"No response returned from server when pushing model: "+httplib::to_string( res.error() ) );}
35631 std::string get_version()
35633 std::string version;
35635 auto res = this->cli->Get(
"/api/version");
35639 json response = json::parse(res->body);
35640 version = response[
"version"];
35651 void setServerURL(
const std::string& server_url)
35653 this->server_url = server_url;
35658 void setReadTimeout(
const int seconds)
35660 this->cli->set_read_timeout(seconds);
35663 void setWriteTimeout(
const int seconds)
35665 this->cli->set_write_timeout(seconds);
35678 std::string server_url;
35689 inline void setServerURL(
const std::string& server_url)
35691 ollama.setServerURL(server_url);
35694 inline ollama::response generate(
const std::string& model,
const std::string& prompt,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35696 return ollama.generate(model, prompt, options, images);
35699 inline ollama::response generate(
const std::string& model,
const std::string& prompt,
const ollama::response& context,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35701 return ollama.generate(model, prompt, context, options, images);
35706 return ollama.generate(request);
35709 inline bool generate(
const std::string& model,
const std::string& prompt, std::function<
bool(
const ollama::response&)> on_receive_response,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35711 return ollama.generate(model, prompt, on_receive_response, options, images);
35714 inline bool generate(
const std::string& model,
const std::string& prompt,
ollama::response& context, std::function<
bool(
const ollama::response&)> on_receive_response,
const json& options=
nullptr,
const std::vector<std::string>& images=std::vector<std::string>())
35716 return ollama.generate(model, prompt, context, on_receive_response, options, images);
35721 return ollama.generate(request, on_receive_response);
35724 inline ollama::response chat(
const std::string& model,
const ollama::messages& messages,
const json& options=
nullptr,
const std::string& format=
"json",
const std::string& keep_alive_duration=
"5m")
35726 return ollama.chat(model, messages, options, format, keep_alive_duration);
35731 return ollama.chat(request);
35734 inline bool chat(
const std::string& model,
const ollama::messages& messages, std::function<
bool(
const ollama::response&)> on_receive_response,
const json& options=
nullptr,
const std::string& format=
"json",
const std::string& keep_alive_duration=
"5m")
35736 return ollama.chat(model, messages, on_receive_response, options, format, keep_alive_duration);
35741 return ollama.chat(request, on_receive_response);
35744 inline bool create(
const std::string& modelName,
const std::string& modelFile,
bool loadFromFile=
true)
35746 return ollama.create_model(modelName, modelFile, loadFromFile);
35749 inline bool is_running()
35751 return ollama.is_running();
35754 inline bool load_model(
const std::string& model)
35756 return ollama.load_model(model);
35759 inline std::string get_version()
35761 return ollama.get_version();
35764 inline std::vector<std::string> list_models()
35766 return ollama.list_models();
35769 inline json list_model_json()
35771 return ollama.list_model_json();
35774 inline std::vector<std::string> list_running_models()
35776 return ollama.list_running_models();
35779 inline json running_model_json()
35781 return ollama.running_model_json();
35784 inline bool blob_exists(
const std::string& digest)
35786 return ollama.blob_exists(digest);
35789 inline bool create_blob(
const std::string& digest)
35791 return ollama.create_blob(digest);
35794 inline json show_model_info(
const std::string& model,
bool verbose=
false)
35796 return ollama.show_model_info(model, verbose);
35799 inline bool copy_model(
const std::string& source_model,
const std::string& dest_model)
35801 return ollama.copy_model(source_model, dest_model);
35804 inline bool delete_model(
const std::string& model)
35806 return ollama.delete_model(model);
35809 inline bool pull_model(
const std::string& model,
bool allow_insecure =
false)
35811 return ollama.pull_model(model, allow_insecure);
35814 inline bool push_model(
const std::string& model,
bool allow_insecure =
false)
35816 return ollama.push_model(model, allow_insecure);
35819 inline ollama::response generate_embeddings(
const std::string& model,
const std::string& input,
const json& options=
nullptr,
bool truncate =
true,
const std::string& keep_alive_duration=
"5m")
35821 return ollama.generate_embeddings(model, input, options, truncate, keep_alive_duration);
35826 return ollama.generate_embeddings(request);
35829 inline void setReadTimeout(
const int& seconds)
35831 ollama.setReadTimeout(seconds);
35834 inline void setWriteTimeout(
const int& seconds)
35836 ollama.setWriteTimeout(seconds);
Definition ollama.hpp:35159
namespace for Niels Lohmann
Definition ollama.hpp:19424
constexpr bool is_string() const noexcept
return whether value is a string
Definition ollama.hpp:20696
number_integer_t * get_impl_ptr(number_integer_t *) noexcept
get a pointer to the value (integer number)
Definition ollama.hpp:20789
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition ollama.hpp:21929
reference operator[](KeyType &&key)
access specified object element
Definition ollama.hpp:21497
json_value(object_t &&value)
constructor for rvalue objects
Definition ollama.hpp:19859
size_type size() const noexcept
returns the number of elements
Definition ollama.hpp:22270
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition ollama.hpp:23703
json_value(typename binary_t::container_type &&value)
constructor for rvalue binary arrays
Definition ollama.hpp:19871
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition ollama.hpp:23635
number_unsigned_t number_unsigned
number (unsigned integer)
Definition ollama.hpp:19763
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
get a (pointer) value (explicit)
Definition ollama.hpp:21069
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition ollama.hpp:22127
reference back()
access the last element
Definition ollama.hpp:21733
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition ollama.hpp:20160
number_float_t number_float
number (floating-point)
Definition ollama.hpp:19765
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition ollama.hpp:22143
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition ollama.hpp:24295
json_value(const array_t &value)
constructor for arrays
Definition ollama.hpp:19862
array_t * get_impl_ptr(array_t *) noexcept
get a pointer to the value (array)
Definition ollama.hpp:20753
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition ollama.hpp:23483
const_reference front() const
access the first element
Definition ollama.hpp:21726
constexpr bool is_array() const noexcept
return whether value is an array
Definition ollama.hpp:20689
number_float_t * get_impl_ptr(number_float_t *) noexcept
get a pointer to the value (floating-point number)
Definition ollama.hpp:20813
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition ollama.hpp:22787
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition ollama.hpp:21677
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition ollama.hpp:22046
constexpr const number_integer_t * get_impl_ptr(const number_integer_t *) const noexcept
get a pointer to the value (integer number)
Definition ollama.hpp:20795
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition ollama.hpp:19555
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition ollama.hpp:23654
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition ollama.hpp:19499
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition ollama.hpp:20661
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition ollama.hpp:19559
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition ollama.hpp:23898
basic_json get_impl(detail::priority_tag< 3 >) const
get special-case overload
Definition ollama.hpp:21021
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a BJData serialization of a given JSON value
Definition ollama.hpp:23646
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition ollama.hpp:23943
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition ollama.hpp:19550
static JSON_HEDLEY_RETURNS_NON_NULL T * create(Args &&... args)
helper for exception-safe object creation
Definition ollama.hpp:19703
std::size_t size_type
a type to represent container sizes
Definition ollama.hpp:19542
constexpr bool is_structured() const noexcept
return whether type is structured
Definition ollama.hpp:20633
json_value(boolean_t v) noexcept
constructor for booleans
Definition ollama.hpp:19770
const_reference operator[](KeyType &&key) const
access specified object element
Definition ollama.hpp:21521
boolean_t get_impl(boolean_t *) const
get a boolean (explicit)
Definition ollama.hpp:20730
void swap(binary_t &other)
exchanges the values
Definition ollama.hpp:22864
ReferenceType get_ref()
get a reference value (implicit)
Definition ollama.hpp:21159
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition ollama.hpp:22309
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition ollama.hpp:22733
ReferenceType get_ref() const
get a reference value (implicit)
Definition ollama.hpp:21170
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition ollama.hpp:20710
reference operator+=(initializer_list_t init)
add an object to an object
Definition ollama.hpp:22525
void push_back(basic_json &&val)
add an object to an array
Definition ollama.hpp:22413
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition ollama.hpp:21466
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition ollama.hpp:22215
json_value(number_integer_t v) noexcept
constructor for numbers (integer)
Definition ollama.hpp:19772
static ReferenceType get_ref_impl(ThisType &obj)
helper function to implement get_ref()
Definition ollama.hpp:20848
const_reference back() const
access the last element
Definition ollama.hpp:21742
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition ollama.hpp:21824
reference operator+=(const basic_json &val)
add an object to an array
Definition ollama.hpp:22470
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition ollama.hpp:22804
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition ollama.hpp:23799
constexpr const string_t * get_impl_ptr(const string_t *) const noexcept
get a pointer to the value (string)
Definition ollama.hpp:20771
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition ollama.hpp:20297
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition ollama.hpp:22637
object_t * get_impl_ptr(object_t *) noexcept
get a pointer to the value (object)
Definition ollama.hpp:20741
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition ollama.hpp:23883
static allocator_type get_allocator()
returns the allocator associated with the container
Definition ollama.hpp:19565
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition ollama.hpp:19690
reference at(KeyType &&key)
access specified object element with bounds checking
Definition ollama.hpp:21329
iterator end() noexcept
returns an iterator to one past the last element
Definition ollama.hpp:22118
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition ollama.hpp:20668
json_value(array_t &&value)
constructor for rvalue arrays
Definition ollama.hpp:19865
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition ollama.hpp:22740
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition ollama.hpp:23662
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition ollama.hpp:22150
void push_back(initializer_list_t init)
add an object to an object
Definition ollama.hpp:22509
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition ollama.hpp:20127
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition ollama.hpp:20338
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition ollama.hpp:23601
iterator begin() noexcept
returns an iterator to the first element
Definition ollama.hpp:22093
array_t * array
array (stored with pointer to save storage)
Definition ollama.hpp:19753
void assert_invariant(bool check_parents=true) const noexcept
checks the class invariants
Definition ollama.hpp:20007
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition ollama.hpp:21576
ValueType get_impl(detail::priority_tag< 0 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), std::declval< ValueType & >())))
get a value (explicit)
Definition ollama.hpp:20931
json_value(string_t &&value)
constructor for rvalue strings
Definition ollama.hpp:19853
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition ollama.hpp:22134
constexpr const binary_t * get_impl_ptr(const binary_t *) const noexcept
get a pointer to the value (binary)
Definition ollama.hpp:20831
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition ollama.hpp:23853
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition ollama.hpp:23985
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition ollama.hpp:20308
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition ollama.hpp:20148
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition ollama.hpp:23687
constexpr const number_unsigned_t * get_impl_ptr(const number_unsigned_t *) const noexcept
get a pointer to the value (unsigned number)
Definition ollama.hpp:20807
constexpr const boolean_t * get_impl_ptr(const boolean_t *) const noexcept
get a pointer to the value (boolean)
Definition ollama.hpp:20783
basic_json flatten() const
return flattened JSON value
Definition ollama.hpp:23999
constexpr const array_t * get_impl_ptr(const array_t *) const noexcept
get a pointer to the value (array)
Definition ollama.hpp:20759
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition ollama.hpp:23814
json_value(number_unsigned_t v) noexcept
constructor for numbers (unsigned)
Definition ollama.hpp:19774
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition ollama.hpp:21940
json_value(const string_t &value)
constructor for strings
Definition ollama.hpp:19850
const binary_t & get_binary() const
get a binary value
Definition ollama.hpp:21241
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition ollama.hpp:22657
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition ollama.hpp:24024
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition ollama.hpp:21629
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const std::string &path="")
creates a diff as a JSON patch
Definition ollama.hpp:24305
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition ollama.hpp:23957
json_value(number_float_t v) noexcept
constructor for numbers (floating-point)
Definition ollama.hpp:19776
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition ollama.hpp:19666
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition ollama.hpp:22063
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition ollama.hpp:23571
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition ollama.hpp:23678
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition ollama.hpp:21976
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition ollama.hpp:20286
BasicJsonType get_impl(detail::priority_tag< 2 >) const
get special-case overload
Definition ollama.hpp:20998
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition ollama.hpp:21367
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition ollama.hpp:19573
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition ollama.hpp:20345
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition ollama.hpp:21990
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition ollama.hpp:23562
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition ollama.hpp:21754
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition ollama.hpp:22610
NumberFloatType number_float_t
a type for a number (floating-point)
Definition ollama.hpp:19686
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition ollama.hpp:21551
string_t * string
string (stored with pointer to save storage)
Definition ollama.hpp:19755
AllocatorType< basic_json > allocator_type
the allocator type
Definition ollama.hpp:19545
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition ollama.hpp:19548
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition ollama.hpp:20597
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition ollama.hpp:24447
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition ollama.hpp:21123
reference at(size_type idx)
access specified array element with bounds checking
Definition ollama.hpp:21263
iterator find(KeyType &&key)
find an element in a JSON object
Definition ollama.hpp:22006
binary_t * binary
binary (stored with pointer to save storage)
Definition ollama.hpp:19757
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition ollama.hpp:20675
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition ollama.hpp:22157
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition ollama.hpp:23608
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition ollama.hpp:23971
BooleanType boolean_t
a type for a boolean
Definition ollama.hpp:19674
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
Definition ollama.hpp:19653
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition ollama.hpp:22501
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition ollama.hpp:22109
constexpr const number_float_t * get_impl_ptr(const number_float_t *) const noexcept
get a pointer to the value (floating-point number)
Definition ollama.hpp:20819
reference operator[](typename object_t::key_type key)
access specified object element
Definition ollama.hpp:21444
string_t * get_impl_ptr(string_t *) noexcept
get a pointer to the value (string)
Definition ollama.hpp:20765
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition ollama.hpp:20881
~basic_json() noexcept
destructor
Definition ollama.hpp:20579
json_value(binary_t &&value)
constructor for rvalue binary arrays (internal type)
Definition ollama.hpp:19877
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition ollama.hpp:22178
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition ollama.hpp:20227
json_value(const object_t &value)
constructor for objects
Definition ollama.hpp:19856
void swap(typename binary_t::container_type &other)
exchanges the values
Definition ollama.hpp:22880
binary_t & get_binary()
get a binary value
Definition ollama.hpp:21229
const_iterator begin() const noexcept
returns an iterator to the first element
Definition ollama.hpp:22102
constexpr bool is_number() const noexcept
return whether value is a number
Definition ollama.hpp:20654
number_unsigned_t * get_impl_ptr(number_unsigned_t *) noexcept
get a pointer to the value (unsigned number)
Definition ollama.hpp:20801
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition ollama.hpp:22708
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition ollama.hpp:23745
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition ollama.hpp:21110
reference operator[](size_type idx)
access specified array element
Definition ollama.hpp:21385
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition ollama.hpp:20556
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition ollama.hpp:23627
NumberIntegerType number_integer_t
a type for a number (integer)
Definition ollama.hpp:19678
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition ollama.hpp:20870
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition ollama.hpp:21347
binary_t * get_impl_ptr(binary_t *) noexcept
get a pointer to the value (binary)
Definition ollama.hpp:20825
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition ollama.hpp:20703
void swap(object_t &other)
exchanges the values
Definition ollama.hpp:22832
constexpr auto get_impl(detail::priority_tag< 4 >) const noexcept -> decltype(std::declval< const basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition ollama.hpp:21034
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition ollama.hpp:24008
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition ollama.hpp:22688
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition ollama.hpp:20319
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition ollama.hpp:22208
bool empty() const noexcept
checks whether the container is empty.
Definition ollama.hpp:22231
void swap(array_t &other)
exchanges the values
Definition ollama.hpp:22816
void erase(const size_type idx)
remove element from a JSON array given an index
Definition ollama.hpp:21947
reference operator+=(basic_json &&val)
add an object to an array
Definition ollama.hpp:22438
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition ollama.hpp:22070
ValueType get_impl(detail::priority_tag< 1 >) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >())))
get a value (explicit); special case
Definition ollama.hpp:20973
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition ollama.hpp:20619
reference emplace_back(Args &&... args)
add an object to an array
Definition ollama.hpp:22534
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition ollama.hpp:21652
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition ollama.hpp:20330
StringType string_t
a type for a string
Definition ollama.hpp:19670
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
Definition ollama.hpp:19662
void push_back(const basic_json &val)
add an object to an array
Definition ollama.hpp:22446
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition ollama.hpp:21602
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition ollama.hpp:21309
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition ollama.hpp:23868
json_value m_value
the value of the current element
Definition ollama.hpp:23520
number_integer_t number_integer
number (integer)
Definition ollama.hpp:19761
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition ollama.hpp:22171
json_sax< basic_json > json_sax_t
SAX interface type, see nlohmann::json_sax.
Definition ollama.hpp:19503
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition ollama.hpp:20647
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition ollama.hpp:22036
reference front()
access the first element
Definition ollama.hpp:21719
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition ollama.hpp:20626
constexpr bool is_null() const noexcept
return whether value is null
Definition ollama.hpp:20640
void clear() noexcept
clears the contents
Definition ollama.hpp:22352
constexpr const object_t * get_impl_ptr(const object_t *) const noexcept
get a pointer to the value (object)
Definition ollama.hpp:20747
json_value(value_t t)
constructor for empty values of a given type
Definition ollama.hpp:19778
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition ollama.hpp:23619
json_value()=default
default constructor (for null values)
basic_json(basic_json &&other) noexcept
move constructor
Definition ollama.hpp:20539
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition ollama.hpp:19553
basic_json(const value_t v)
create an empty value with a given type
Definition ollama.hpp:20140
const_reference operator[](size_type idx) const
access specified array element
Definition ollama.hpp:21431
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition ollama.hpp:19540
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition ollama.hpp:22630
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition ollama.hpp:22164
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition ollama.hpp:19682
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition ollama.hpp:23468
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition ollama.hpp:23585
void swap(string_t &other)
exchanges the values
Definition ollama.hpp:22848
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition ollama.hpp:20174
NLOHMANN_BASIC_JSON_TPL basic_json_t
workaround type for MSVC
Definition ollama.hpp:19449
boolean_t * get_impl_ptr(boolean_t *) noexcept
get a pointer to the value (boolean)
Definition ollama.hpp:20777
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition ollama.hpp:19557
json_value(const binary_t &value)
constructor for binary arrays (internal type)
Definition ollama.hpp:19874
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition ollama.hpp:21286
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition ollama.hpp:19694
basic_json(const basic_json &other)
copy constructor
Definition ollama.hpp:20470
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition ollama.hpp:22478
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition ollama.hpp:22559
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition ollama.hpp:23578
constexpr bool is_object() const noexcept
return whether value is an object
Definition ollama.hpp:20682
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition ollama.hpp:23594
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition ollama.hpp:23760
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition ollama.hpp:22591
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition ollama.hpp:20357
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition ollama.hpp:22054
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition ollama.hpp:23671
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition ollama.hpp:22022
boolean_t boolean
boolean
Definition ollama.hpp:19759
json_value(const typename binary_t::container_type &value)
constructor for binary arrays
Definition ollama.hpp:19868
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition ollama.hpp:19491
an internal type for a backed binary type
Definition ollama.hpp:5914
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition ollama.hpp:5920
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition ollama.hpp:5942
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition ollama.hpp:5930
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition ollama.hpp:5969
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition ollama.hpp:5935
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition ollama.hpp:5976
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition ollama.hpp:5925
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition ollama.hpp:5961
void clear_subtype() noexcept
clears the binary subtype
Definition ollama.hpp:5983
deserialization of CBOR, MessagePack, and UBJSON values
Definition ollama.hpp:9235
bool get_string(const input_format_t format, const NumberType len, string_t &result)
create a string by reading characters from the input
Definition ollama.hpp:11998
bool get_ubjson_size_type(std::pair< std::size_t, char_int_type > &result, bool inside_ndarray=false)
determine the type and size for a container
Definition ollama.hpp:11399
bool parse_bson_array()
Reads an array from the BSON input and passes it to the SAX-parser.
Definition ollama.hpp:9557
bool parse_bson_element_list(const bool is_array)
Read a BSON element list (as specified in the BSON-spec)
Definition ollama.hpp:9519
bool parse_msgpack_internal()
Definition ollama.hpp:10363
std::string get_token_string() const
Definition ollama.hpp:12068
bool get_msgpack_string(string_t &result)
reads a MessagePack string
Definition ollama.hpp:10744
std::string exception_message(const input_format_t format, const std::string &detail, const std::string &context) const
Definition ollama.hpp:12081
InputAdapterType ia
input adapter
Definition ollama.hpp:12121
bool get_binary(const input_format_t format, const NumberType len, binary_t &result)
create a byte array by reading bytes from the input
Definition ollama.hpp:12031
char_int_type get_ignore_noop()
Definition ollama.hpp:11928
bool get_ubjson_value(const char_int_type prefix)
Definition ollama.hpp:11466
bool get_ubjson_ndarray_size(std::vector< size_t > &dim)
Definition ollama.hpp:11111
bool parse_bson_element_internal(const char_int_type element_type, const std::size_t element_type_parse_position)
Read a BSON document element of the given element_type.
Definition ollama.hpp:9439
bool get_msgpack_object(const std::size_t len)
Definition ollama.hpp:10960
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition ollama.hpp:9251
bool parse_bson_internal()
Reads in a BSON-object and passes it to the SAX-parser.
Definition ollama.hpp:9335
bool get_cbor_object(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition ollama.hpp:10307
bool get_cbor_binary(binary_t &result)
reads a CBOR byte array
Definition ollama.hpp:10174
bool get_ubjson_array()
Definition ollama.hpp:11649
bool get_bson_cstr(string_t &result)
Parses a C-style string from the BSON input.
Definition ollama.hpp:9360
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition ollama.hpp:9272
bool get_cbor_array(const std::size_t len, const cbor_tag_handler_t tag_handler)
Definition ollama.hpp:10269
bool get_msgpack_array(const std::size_t len)
Definition ollama.hpp:10938
char_int_type get()
get next character from the input
Definition ollama.hpp:11919
bool get_msgpack_binary(binary_t &result)
reads a MessagePack byte array
Definition ollama.hpp:10827
bool parse_ubjson_internal(const bool get_char=true)
Definition ollama.hpp:10997
bool get_ubjson_size_value(std::size_t &result, bool &is_ndarray, char_int_type prefix=0)
Definition ollama.hpp:11176
bool parse_cbor_internal(const bool get_char, const cbor_tag_handler_t tag_handler)
Definition ollama.hpp:9587
bool get_ubjson_object()
Definition ollama.hpp:11757
bool get_bson_string(const NumberType len, string_t &result)
Parses a zero-terminated string of length len from the BSON input.
Definition ollama.hpp:9390
bool get_ubjson_string(string_t &result, const bool get_char=true)
reads a UBJSON string
Definition ollama.hpp:11016
bool get_cbor_string(string_t &result)
reads a CBOR string
Definition ollama.hpp:10078
bool get_bson_binary(const NumberType len, binary_t &result)
Parses a byte array input of length len from the BSON input.
Definition ollama.hpp:9412
serialization to CBOR and MessagePack values
Definition ollama.hpp:15102
void write_bson_binary(const string_t &name, const binary_t &value)
Writes a BSON element with key name and binary value value.
Definition ollama.hpp:16211
void write_bson_boolean(const string_t &name, const bool value)
Writes a BSON element with key name and boolean value value.
Definition ollama.hpp:16049
void write_bson(const BasicJsonType &j)
Definition ollama.hpp:15122
void write_bson_integer(const string_t &name, const std::int64_t value)
Writes a BSON element with key name and integer value.
Definition ollama.hpp:16109
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
Definition ollama.hpp:16127
void write_bson_array(const string_t &name, const typename BasicJsonType::array_t &value)
Writes a BSON element with key name and array value.
Definition ollama.hpp:16192
bool write_bjdata_ndarray(const typename BasicJsonType::object_t &value, const bool use_count, const bool use_type)
Definition ollama.hpp:16680
void write_bson_string(const string_t &name, const string_t &value)
Writes a BSON element with key name and string value value.
Definition ollama.hpp:16077
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition ollama.hpp:15113
void write_bson_element(const string_t &name, const BasicJsonType &j)
Serializes the JSON value j to BSON and associates it with the key name.
Definition ollama.hpp:16274
void write_bson_object(const typename BasicJsonType::object_t &value)
Definition ollama.hpp:16336
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false)
Definition ollama.hpp:15801
void write_bson_double(const string_t &name, const double value)
Writes a BSON element with key name and double value value.
Definition ollama.hpp:16059
static std::size_t calc_bson_string_size(const string_t &value)
Definition ollama.hpp:16069
static std::size_t calc_bson_entry_header_size(const string_t &name, const BasicJsonType &j)
Definition ollama.hpp:16022
void write_bson_null(const string_t &name)
Writes a BSON element with key name and null value.
Definition ollama.hpp:16091
CharType ubjson_prefix(const BasicJsonType &j, const bool use_bjdata) const noexcept
determine the type prefix of container values
Definition ollama.hpp:16566
void write_bson_unsigned(const string_t &name, const BasicJsonType &j)
Writes a BSON element with key name and unsigned value.
Definition ollama.hpp:16137
static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t &value)
Definition ollama.hpp:16184
static std::size_t calc_bson_element_size(const string_t &name, const BasicJsonType &j)
Calculates the size necessary to serialize the JSON value j with its name.
Definition ollama.hpp:16226
void write_msgpack(const BasicJsonType &j)
Definition ollama.hpp:15475
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t &value)
Calculates the size of the BSON serialization of the given JSON-object j.
Definition ollama.hpp:16321
void write_cbor(const BasicJsonType &j)
Definition ollama.hpp:15151
void write_bson_entry_header(const string_t &name, const std::uint8_t element_type)
Writes the given element_type and name to the output adapter.
Definition ollama.hpp:16037
void write_bson_object_entry(const string_t &name, const typename BasicJsonType::object_t &value)
Writes a BSON element with key name and object value.
Definition ollama.hpp:16159
static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t &value)
Definition ollama.hpp:16169
static std::size_t calc_bson_integer_size(const std::int64_t value)
Definition ollama.hpp:16099
general exception of the basic_json class
Definition ollama.hpp:4395
const int id
the id of the exception
Definition ollama.hpp:4404
std::runtime_error m
an exception object as storage for error messages
Definition ollama.hpp:4487
const char * what() const noexcept override
returns the explanatory string
Definition ollama.hpp:4398
exception indicating errors with iterators
Definition ollama.hpp:4546
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition ollama.hpp:12939
iter_impl operator+(difference_type i) const
add to iterator
Definition ollama.hpp:13513
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition ollama.hpp:13076
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition ollama.hpp:13458
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition ollama.hpp:13066
bool operator<(const iter_impl &other) const
comparison: smaller
Definition ollama.hpp:13405
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition ollama.hpp:13440
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition ollama.hpp:13504
iter_impl & operator--()
pre-decrement (–it)
Definition ollama.hpp:13319
const object_t::key_type & key() const
return the key of an object iterator
Definition ollama.hpp:13613
bool operator==(const IterImpl &other) const
comparison: equal
Definition ollama.hpp:13360
iter_impl operator++(int) &
post-increment (it++)
Definition ollama.hpp:13257
iter_impl & operator+=(difference_type i)
add to iterator
Definition ollama.hpp:13467
reference operator[](difference_type n) const
access to successor
Definition ollama.hpp:13575
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition ollama.hpp:12969
pointer operator->() const
dereference the iterator
Definition ollama.hpp:13215
friend other_iter_impl
allow basic_json to access private members
Definition ollama.hpp:12943
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition ollama.hpp:13638
difference_type operator-(const iter_impl &other) const
return difference
Definition ollama.hpp:13546
std::bidirectional_iterator_tag iterator_category
Definition ollama.hpp:12964
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition ollama.hpp:13524
reference value() const
return the value of an iterator
Definition ollama.hpp:13629
bool operator>(const iter_impl &other) const
comparison: greater than
Definition ollama.hpp:13449
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
defines a pointer to the type iterated over (value_type)
Definition ollama.hpp:12973
iter_impl & operator++()
pre-increment (++it)
Definition ollama.hpp:13268
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition ollama.hpp:12967
reference operator*() const
return a reference to the value pointed to by the iterator
Definition ollama.hpp:13171
iter_impl operator-(difference_type i) const
subtract from iterator
Definition ollama.hpp:13535
iter_impl< typename std::conditional< std::is_const< BasicJsonType >::value, typename std::remove_const< BasicJsonType >::type, const BasicJsonType >::type > other_iter_impl
the iterator with BasicJsonType of different const-ness
Definition ollama.hpp:12941
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition ollama.hpp:13051
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition ollama.hpp:13396
iter_impl operator--(int) &
post-decrement (it–)
Definition ollama.hpp:13308
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
defines a reference to the type iterated over (value_type)
Definition ollama.hpp:12978
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition ollama.hpp:13041
void set_end() noexcept
set the iterator past the last value
Definition ollama.hpp:13132
Definition ollama.hpp:5209
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition ollama.hpp:5274
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition ollama.hpp:5280
string_type empty_str
an empty string (to return a reference for primitive values)
Definition ollama.hpp:5228
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition ollama.hpp:5257
std::size_t array_index_last
last stringified array index
Definition ollama.hpp:5224
std::size_t array_index
an index for arrays (used to create key names)
Definition ollama.hpp:5222
IteratorType::reference value() const
return value of the iterator
Definition ollama.hpp:5322
const string_type & key() const
return key of the iterator
Definition ollama.hpp:5286
string_type array_index_str
a string representation of the array index
Definition ollama.hpp:5226
IteratorType anchor
the iterator
Definition ollama.hpp:5220
proxy class for the items() function
Definition ollama.hpp:5330
IteratorType::pointer container
the container to iterate
Definition ollama.hpp:5333
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition ollama.hpp:5355
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition ollama.hpp:5349
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition ollama.hpp:5339
Definition ollama.hpp:14843
a template for a reverse iterator class
Definition ollama.hpp:13692
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition ollama.hpp:13708
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition ollama.hpp:13720
json_reverse_iterator & operator++()
pre-increment (++it)
Definition ollama.hpp:13714
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition ollama.hpp:13732
reference operator[](difference_type n) const
access to successor
Definition ollama.hpp:13756
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition ollama.hpp:13762
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition ollama.hpp:13750
typename Base::reference reference
the reference type for the pointed-to element
Definition ollama.hpp:13698
reference value() const
return the value of an iterator
Definition ollama.hpp:13769
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition ollama.hpp:13705
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition ollama.hpp:13726
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition ollama.hpp:13696
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition ollama.hpp:13744
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition ollama.hpp:13701
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition ollama.hpp:13738
Definition ollama.hpp:7313
Definition ollama.hpp:7006
BasicJsonType & root
the parsed JSON value
Definition ollama.hpp:7292
std::pair< bool, BasicJsonType * > handle_value(Value &&v, const bool skip_callback=false)
Definition ollama.hpp:7228
SAX implementation to create a JSON value from SAX events.
Definition ollama.hpp:6823
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition ollama.hpp:6836
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType * handle_value(Value &&v)
Definition ollama.hpp:6970
BasicJsonType & root
the parsed JSON value
Definition ollama.hpp:6993
Definition ollama.hpp:7430
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition ollama.hpp:7457
token_type
token types for the parser
Definition ollama.hpp:7434
lexical analysis
Definition ollama.hpp:7507
void reset() noexcept
reset token_buffer; current character is beginning of token
Definition ollama.hpp:8715
bool skip_bom()
skip the UTF-8 byte order mark
Definition ollama.hpp:8881
int get_codepoint()
get codepoint from 4 hex characters following \u
Definition ollama.hpp:7564
token_type scan_string()
scan a string literal
Definition ollama.hpp:7649
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition ollama.hpp:8868
std::string get_token_string() const
Definition ollama.hpp:8843
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition ollama.hpp:8807
bool next_byte_in_range(std::initializer_list< char_int_type > ranges)
check if the next byte(s) are inside a given range
Definition ollama.hpp:7612
constexpr position_t get_position() const noexcept
return position of last read token
Definition ollama.hpp:8835
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition ollama.hpp:8813
bool scan_comment()
scan a comment
Definition ollama.hpp:8239
InputAdapterType ia
input adapter
Definition ollama.hpp:8994
token_type scan_number()
scan a number literal
Definition ollama.hpp:8364
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition ollama.hpp:8825
void add(char_int_type c)
add a character to token_buffer
Definition ollama.hpp:8796
void unget()
unget current character (read it again on next get)
Definition ollama.hpp:8769
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition ollama.hpp:8819
static JSON_HEDLEY_PURE char get_decimal_point() noexcept
return the locale-dependent decimal point
Definition ollama.hpp:7538
exception indicating other library errors
Definition ollama.hpp:4598
exception indicating access out of the defined range
Definition ollama.hpp:4581
Definition ollama.hpp:15060
output adapter for output streams
Definition ollama.hpp:15012
output adapter for basic_string
Definition ollama.hpp:15037
output adapter for byte vectors
Definition ollama.hpp:14987
exception indicating a parse error
Definition ollama.hpp:4493
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition ollama.hpp:4505
const std::size_t byte
byte index of the parse error
Definition ollama.hpp:4530
syntax analysis
Definition ollama.hpp:12252
parser(InputAdapterType &&adapter, const parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition ollama.hpp:12262
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition ollama.hpp:12284
lexer_t m_lexer
the lexer
Definition ollama.hpp:12704
bool accept(const bool strict=true)
public accept interface
Definition ollama.hpp:12344
token_type get_token()
get next token from lexer
Definition ollama.hpp:12664
Definition ollama.hpp:12756
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition ollama.hpp:12785
void set_end() noexcept
set iterator to a defined past the end
Definition ollama.hpp:12779
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition ollama.hpp:12791
void set_begin() noexcept
set iterator to a defined beginning
Definition ollama.hpp:12773
Definition ollama.hpp:18083
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition ollama.hpp:18098
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition ollama.hpp:19015
string_t indent_string
the indentation string
Definition ollama.hpp:19012
const char indent_char
the indentation character
Definition ollama.hpp:19010
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition ollama.hpp:18138
exception indicating executing a member function with a wrong type
Definition ollama.hpp:4564
Definition ollama.hpp:25910
Definition ollama.hpp:26336
Definition ollama.hpp:25322
Definition ollama.hpp:25279
Definition ollama.hpp:25263
Definition ollama.hpp:25875
Definition ollama.hpp:25641
Definition ollama.hpp:25450
Definition ollama.hpp:25469
Definition ollama.hpp:25480
Definition ollama.hpp:27063
Definition ollama.hpp:30159
Definition ollama.hpp:25571
Definition ollama.hpp:25597
Definition ollama.hpp:25627
Definition ollama.hpp:27893
Definition ollama.hpp:27083
Definition ollama.hpp:27092
Definition ollama.hpp:27191
Definition ollama.hpp:27103
Definition ollama.hpp:27172
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition ollama.hpp:13864
BasicJsonType & get_checked(BasicJsonType *ptr) const
Definition ollama.hpp:14250
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition ollama.hpp:13959
static BasicJsonType::size_type array_index(const string_t &s)
Definition ollama.hpp:14042
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition ollama.hpp:13966
json_pointer(const string_t &s="")
create JSON pointer
Definition ollama.hpp:13890
static std::vector< string_t > split(const string_t &reference_string)
split the string input to reference tokens
Definition ollama.hpp:14494
bool empty() const noexcept
return whether pointer points to the root document
Definition ollama.hpp:14025
BasicJsonType & get_and_create(BasicJsonType &j) const
create and return a reference to the pointed to value
Definition ollama.hpp:14102
void pop_back()
remove last reference token
Definition ollama.hpp:13987
string_t to_string() const
return a string representation of the JSON pointer
Definition ollama.hpp:13896
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition ollama.hpp:13944
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition ollama.hpp:14018
std::vector< string_t > reference_tokens
the reference tokens
Definition ollama.hpp:14753
static void flatten(const string_t &reference_string, const BasicJsonType &value, BasicJsonType &result)
Definition ollama.hpp:14563
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition ollama.hpp:13926
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition ollama.hpp:13951
BasicJsonType & get_unchecked(BasicJsonType *ptr) const
return a reference to the pointed to value
Definition ollama.hpp:14182
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition ollama.hpp:13973
static BasicJsonType unflatten(const BasicJsonType &value)
Definition ollama.hpp:14635
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition ollama.hpp:13936
const string_t & back() const
return last reference token
Definition ollama.hpp:13999
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition ollama.hpp:13917
const BasicJsonType & get_unchecked(const BasicJsonType *ptr) const
return a const reference to the pointed to value
Definition ollama.hpp:14308
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition ollama.hpp:14011
const BasicJsonType & get_checked(const BasicJsonType *ptr) const
Definition ollama.hpp:14357
bool contains(const BasicJsonType *ptr) const
Definition ollama.hpp:14406
Definition ollama.hpp:34690
Definition ollama.hpp:34879
Definition ollama.hpp:34890
Definition ollama.hpp:34934
Definition ollama.hpp:34888
Definition ollama.hpp:34975
Definition ollama.hpp:34988
Definition ollama.hpp:34958
Definition ollama.hpp:35022
Definition ollama.hpp:35080
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition ollama.hpp:17422
cached_power get_cached_power_for_binary_exponent(int e)
Definition ollama.hpp:17258
boundaries compute_boundaries(FloatType value)
Definition ollama.hpp:17119
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition ollama.hpp:17758
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition ollama.hpp:17517
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition ollama.hpp:17858
detail namespace with internal helper functions
Definition ollama.hpp:272
input_format_t
the supported input formats
Definition ollama.hpp:6199
static void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition ollama.hpp:3028
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition ollama.hpp:14982
parse_event_t
Definition ollama.hpp:12226
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition ollama.hpp:2994
cbor_tag_handler_t
how to treat CBOR tags
Definition ollama.hpp:9208
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_t
the JSON type enumeration
Definition ollama.hpp:2896
@ number_integer
number value (signed integer)
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
static bool little_endianness(int num=1) noexcept
determine system byte order
Definition ollama.hpp:9221
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition ollama.hpp:6045
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition ollama.hpp:2925
error_handler_t
how to treat decoding errors
Definition ollama.hpp:18075
@ strict
throw a type_error exception in case of invalid UTF-8
@ replace
replace invalid UTF-8 sequences with U+FFFD
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition ollama.hpp:3013
Definition ollama.hpp:34688
namespace for Niels Lohmann
Definition ollama.hpp:5856
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition ollama.hpp:5880
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition ollama.hpp:5870
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition ollama.hpp:5860
Definition ollama.hpp:3611
Definition ollama.hpp:3628
Definition ollama.hpp:3683
Definition ollama.hpp:304
Definition ollama.hpp:17106
Definition ollama.hpp:17245
Definition ollama.hpp:16988
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition ollama.hpp:17012
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition ollama.hpp:17094
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition ollama.hpp:17077
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition ollama.hpp:17000
Definition ollama.hpp:5442
Definition ollama.hpp:5122
Definition ollama.hpp:3550
Definition ollama.hpp:3606
Definition ollama.hpp:3575
Definition ollama.hpp:3590
Definition ollama.hpp:4638
Definition ollama.hpp:3146
an iterator value
Definition ollama.hpp:12872
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition ollama.hpp:12876
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition ollama.hpp:12878
Definition ollama.hpp:3499
Definition ollama.hpp:3486
Definition ollama.hpp:4204
Definition ollama.hpp:4000
Definition ollama.hpp:3864
Definition ollama.hpp:3883
Definition ollama.hpp:3931
Definition ollama.hpp:3954
Definition ollama.hpp:3784
Definition ollama.hpp:3804
Definition ollama.hpp:3841
Definition ollama.hpp:3957
Definition ollama.hpp:3970
Definition ollama.hpp:3777
Definition ollama.hpp:3886
Definition ollama.hpp:3927
Definition ollama.hpp:3808
Definition ollama.hpp:3837
Definition ollama.hpp:3848
Definition ollama.hpp:3973
Definition ollama.hpp:3715
Definition ollama.hpp:3696
Definition ollama.hpp:320
Definition ollama.hpp:3558
Definition ollama.hpp:6520
Definition ollama.hpp:3730
Definition ollama.hpp:3979
Definition ollama.hpp:3509
Definition ollama.hpp:4061
Definition ollama.hpp:4057
Definition ollama.hpp:3749
Definition ollama.hpp:9140
Definition ollama.hpp:9109
Definition ollama.hpp:3990
Definition ollama.hpp:4226
Definition ollama.hpp:3314
Definition ollama.hpp:3295
Default base class of the basic_json class.
Definition ollama.hpp:13811
Definition ollama.hpp:275
Definition ollama.hpp:3690
Definition ollama.hpp:290
abstract output adapter interface
Definition ollama.hpp:14968
struct to capture the start position of the current token
Definition ollama.hpp:3059
std::size_t chars_read_current_line
the number of characters read in the current line
Definition ollama.hpp:3063
std::size_t lines_read
the number of lines read
Definition ollama.hpp:3065
std::size_t chars_read_total
the total number of characters read
Definition ollama.hpp:3061
Definition ollama.hpp:3229
Definition ollama.hpp:3235
Definition ollama.hpp:5823
Definition ollama.hpp:3166
Definition ollama.hpp:3185
Definition ollama.hpp:4152
Definition ollama.hpp:4106
Definition ollama.hpp:26190
Definition ollama.hpp:25348
Definition ollama.hpp:25400
Definition ollama.hpp:25812
Definition ollama.hpp:25522
Definition ollama.hpp:25129
Definition ollama.hpp:25142
Definition ollama.hpp:13874
SAX interface.
Definition ollama.hpp:6693
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition ollama.hpp:19057
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition ollama.hpp:24543